个人工具
119.28.94.63
该IP地址的讨论
登录
查看“UbuntuManual:编程”的源代码 - Ubuntu中文
页面
讨论
查看源代码
历史
搜索
导航
首页
最近更改
随机页面
页面分类
帮助
编辑
编辑指南
沙盒
新闻动态
字词处理
工具
链入页面
相关更改
特殊页面
页面信息
查看“UbuntuManual:编程”的源代码
来自Ubuntu中文
←
UbuntuManual:编程
跳转至:
导航
,
搜索
因为以下原因,你没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
{{UbuntuManual}} == 第 13 章 - 编程 == 不要用“test”命名可执行的测试文件。test是一个shell的内建命令。 === 从哪儿开始 === 参考资源: * /usr/share/doc/package下的文档和样例 * [http://arioch.unomaha.edu/~jclark/#info Unix / Programming Information] * ''Linux Programming Bible'' (John Goerzen/IDG books) 更详细的文档可以从[http://www.gnu.org/ GNU]获得打印版本。 接下来的四个小节中包含了用不同的编程语言编写的脚本样例,该脚本创建一个包含用户帐户信息的文本文件,调用一组进程如newusers程序,将这些信息加入到/etc/passwd。每个脚本均需要一个输入文件,该文件应包含格式如first_name last_name password的行。(这些脚本并不创建真正的用户目录。) === Shell === 理解类Unix系统如何工作的'''最好'''方法就是阅读shell脚本。在此,我们就shell编程做个简单的介绍。 参阅 [http://www.greenend.org.uk/rjk/2001/04/shell.html Shell Mistakes] 来学习更多的错误。 ==== Bash – GNU标准交互式shell ==== Bash参考资源: * bash(1) * info bash * LDP [http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html BASH Programming - Introduction HOWTO] 作为开始信息。 * mc /usr/share/doc/bash/examples/ /usr/share/doc/bash/ (安装bash-doc软件包阅读样例文件。) * ''Learning the bash Shell'', 2nd edition (O'Reilly) 一个简短的程序样例(从标准输入端创建帐户信息供newusers使用): <pre><nowiki> #!/bin/bash # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain pid=1000; while read n1 n2 n3 ; do if [ ${n1:0:1} !== "#" ]; then let pid=$pid+1 echo ${n1}_${n2}:password:${pid}:${pid}:,,,/home/${n1}_${n2}:/bin/bash fi done </nowiki></pre> ==== POSIX shells ==== Ubuntu 中有几个软件包提供了POSIX shell: * dash (Sarge) ** Priority: optional ** Installed-Size: 176 ** 到目前为止最小和最快的 – 最适合用在初始化安装中 * ash (Woody) ** Priority: optional ** Installed-Size: 180 ** 较小和较快的 – 比较适合用在初始化安装中 * bash ** Essential: yes ** Priority: required ** Installed-Size: 580 ** 较大和多特征的 – 应用了许多扩展 * pdksh ** Priority: optional ** Installed-Size: 408 ** 完全跟 AT&T 的 ksh 类似 如果你想编写具有通用性的shell脚本,最好写POSIX shell脚本。可将/bin/sh链接到ash或(dash)来测试脚本的POSIX兼容性。 避免用 bash 化 或 zsh 化的思维去编写脚本。 例如,应避免: * if [ foo ==== bar ] ; then ... * diff -u file.c{.orig,} * mkdir /foo{bar,baz} 本文档的 shell 描述,只适用于 POSIX 类型的 shell,不适用于包括 tcsh 在内的 csh 类型。 ==== Shell参数 ==== 几个需要记住的'''特殊参数''': <pre><nowiki> $0 === shell名称或shel脚本名称 $1 === 第一个(1)shell参数 ... $9 === 第九个(9)shell参数 $# === 位置参数的个数 "$*" === "$1 $2 $3 $4 ... $n" "$@" === "$1" "$2" "$3" "$4" ... "$n" $? === 最近执行的命令的退出状态 $$ === 当前shell脚本的PID $! === 最近启动的后台作业的PID </nowiki></pre> 需要记住的基本'''扩展参数''': <pre><nowiki> 形式 如果设置了 var 如果没有设置 var ${var:-string} $var string ${var:+string} string null ${var:=string} $var string (并且执行var=string) ${var:?string} $var (返回string然后退出) </nowiki></pre> 在此,冒号“:”在所有运算表达式中事实上均是可选的。 * 有“:” === 运算表达式测试“存在”和“非空”。 * 没有“:” === 运算表达式仅测试“存在”。 需要记住的'''替换参数''': <pre><nowiki> 形式 结果 ${var%suffix} 删除位于var结尾的suffix最小匹配模式 ${var%%suffix} 删除位于var结尾的suffix最大匹配模式 ${var#prefix} 删除位于var开头的prefix最小匹配模式 ${var##prefix} 删除位于var开头的prefix最大匹配模式 </nowiki></pre> ==== Shell重定向 ==== 需要记住的基本'''重定向'''(redirection)运算符(在此[n]表示定义文件描述符的可选参数): <pre><nowiki> [n]> file 重定向标准输出(或 n)到file。 [n]>> file 重定向标准输出(或 n)到file。 [n]< file 将file重定向到标准输入(或 n)。 [n1]>&n2 重定向标准输出(或 n1)到n2。 2> file >&2 重定向标准输出和错误输出到file。 | command 将标准输出通过管道传递给command。 2>&1 | command 将标准输出或错误输出通过管道传递给command。 </nowiki></pre> 在这里: * stdin: 标准输入 (文件描述符 === 0) * stdout: 标准输出 (文件描述符 === 1) * stderr: 标准错误 (文件描述符 === 2) shell 允许你通过使用 exec 内嵌一个任意的文件描述符来打开文件。 <pre><nowiki> $ echo Hello >foo $ exec 3<foo 4>bar # 打开文件 $ cat <&3 >&4 # 重定向标准输入到 3,标准输出到 4 $ exec 3<&- 4>&- # 关闭文件 $ cat bar Hello </nowiki></pre> 在这里, n<&- 和 n>&- 表示关闭文件描述符 n。 ==== Shell条件表达式 ==== 每条命令均可返回一个'''退出状态''',这个状态值可用于条件表达式: * 成功:0 (True) * 错误:1–255 (False) 注意该用法,返回值0用来表示“true”与计算机其它领域中常见的转换是不同的。另外`['等阶于使用test命令进行参数赋值`]'相当于一个条件表达式。 需要记住的常用基本'''条件表达式''': <pre><nowiki> command && if_success_run_this_command_too || true command || if_not_success_run_this_command_instead if [ conditional_expression ]; then if_success_run_this_command else if_not_success_run_this_command fi </nowiki></pre> 当 shell 使用 -e 调用的时候, 需要使用 || true 来确保这个 shell 不会在本行意外退出。 在条件表达式中使用的'''文件'''比较运算符有: <pre><nowiki> -e file file存在则返回True。 -d file file存在且是一个目录则返回True。 -f file 如果file存在且是一个普通文件则返回True。 -w file 如果file存在且可写则返回True。 -x file 如果file存在且可执行则返回True。 file1 -nt file2 如果file1比file2新则返回True。(指修改日期) file1 -ot file2 如果file1比file2旧则返回True。(指修改日期) file1 -ef file2 如果两者是相同的设备和具有相同的结点(inode)数则返回True。 </nowiki></pre> 条件表达式中使用的'''字符串'''比较运算符有: <pre><nowiki> -z str 如果str长度为零则返回True。 -n str 如果str长度为非零则返回True。 str1 ==== str2 如果字符串相等则返回True。 str1 === str2 如果字符串相等则返回True。 (使用"=="代替"="符合严格意义上的POSIX兼容) str1 !== str2 如果字符串不相等则返回True。 str1 < str2 如果str1排在str2之前则返回True(与当前位置有关)。 str1 > str2 如果str1排在str2之后则返回True(与当前位置有关)。 </nowiki></pre> 条件表达式中的'''算术'''整数比较运算符有-eq、-ne、-lt、-le、-gt和-ge。 ==== 命令行处理 ==== shell按如下的方式处理脚本: * 用这些元字符将其分割成'''tokens''':SPACE, TAB, NEWLINE, ;, (, ), <, >, |, & * 如果不在"..."或'...'内就检查'''keyword'''(循环检查) * 如果不在"..."或'...'内就扩展'''alias'''(循环检查) * 如果不在"..."或'...'内就扩展'''brace''',a{1,2} -> a1 a2 * 如果不在"..."或'...'内就扩展'''tilde''', ~user -> user's home directory * 如果不在'...'内就扩展'''parameter''', $PARAMETER * 如果不在'...'内就扩展'''command substitution''', $(command) * 如果不在"..."或'...'内就用$IFS分割成'''words''' * 如果不在"..."或'...'内就扩展'''pathname''' *?[] * 查找'''command''' ** function ** built-in ** file in $PATH * 循环 在双单号内单引号将失效。 在 shell 里执行 set -x 或者使用 -x 选项调用 shell, 该 shell 将会显示出所有执行的命令。 这对调试非常有用。 === Awk === Awk的参考资源: * ''Effective awk Programming'', 3rd edition (O'Reilly) * ''Sed & awk'', 2nd edition (O'Reilly) * mawk(1) 和 gawk(1) * info gawk 简短的程序样例(创建newusers命令输入): <pre><nowiki> #!/usr/bin/awk -f # Script to create a file suitable for use in the 'newusers' command, # from a file consisting of user IDs and passwords in the form: # first_name last_name password # Copyright (c) KMSelf Sat Aug 25 20:47:38 PDT 2001 # Distributed under GNU GPL v 2, or at your option, any later version. # This program is distributed WITHOUT ANY WARRANTY. BEGIN { # Assign starting UID, GID if ( ARGC > 2 ) { startuid === ARGV[1] delete ARGV[1] } else { printf( "Usage: newusers startUID file\n" \ " where:\n" \ " startUID is the starting userid to add, and\n" \ " file is an input file in form:\n" \ " first_name last_name password\n" \ ) exit } infile === ARGV[1] printf( "Starting UID: %s\n\n", startuid ) } /^#/ { next } { ++record first === $1 last === $2 passwd === $3 user== substr( tolower( first ), 1, 1 ) tolower( last ) uid === startuid + record - 1 gid === uid printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n", \ user, passwd, uid, gid, first, last, user \ ) } </nowiki></pre> Ubuntu 中有两个软件包提供了POSIX awk: * mawk ** Priority: required ** Installed-Size: 228 ** 较小和较快 – 适于默认安装 ** 编译时的限制存在 *** NF === 32767 *** sprintf buffer === 1020 * gawk ** Priority: optional ** Installed-Size: 1708 ** 较大和多特征的 – 应用了许多扩展 *** System V Release 4 version of UNIX *** Bell Labs awk *** GNU-specific === Perl === 运行于类Unix系统上的'''解释器'''。 Perl参考资源: * perl(1) * ''Programming Perl'', 3rd edition (O'Reilly) * [http://www.perl.org/ The Perl Directory] 简短的程序样例(创建newusers命令输入): <pre><nowiki> #!/usr/bin/perl # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain $pid=1000; while (<STDIN>) { if (/^#/) { next;} chop; $pid++; ($n1, $n2, $n3) === split / /; print $n1,"_",$n2,":", $n3, ":",$pid, ":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n" } </nowiki></pre> 安装Perl模块module_name: <pre><nowiki> # perl -MCPAN -e 'install module_name' </nowiki></pre> === Python === 一个不错的面向对象的解释器。 Python参考资源: * python(1) * ''Learning Python'' (O'Reilly). * [http://www.python.org/ Python Programming Language] 简短的程序样例(创建newusers命令输入): <pre><nowiki> #! /usr/bin/env python import sys, string # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain # Ported from awk script by KMSelf Sat Aug 25 20:47:38 PDT 2001 # This program is distributed WITHOUT ANY WARRANTY. def usages(): print \ "Usage: ", sys.argv[0], " start_UID [filename]\n" \ "\tstartUID is the starting userid to add.\n" \ "\tfilename is input filename. If not specified, standard input.\n\n" \ "Input file format:\n"\ "\tfirst_name last_name password\n" return 1 def parsefile(startuid): # # main filtering # uid === startuid while 1: line === infile.readline() if not line: break if line[0] ==== '#': continue (first, last, passwd) === string.split(string.lower(line)) # above crashes with wrong # of parameters :-) user === first[0] + last gid === uid lineout === "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" % \ (user, passwd, uid, gid, first, last, user) sys.stdout.write(lineout) +uid if <u>name</u> ==== '<u>main</u>': if len(sys.argv) ==== 1: usages() else: uid === int(sys.argv[1]) #print "# UID start from: %d\n" % uid if len(sys.argv) > 1: infilename === string.join(sys.argv[2:]) infile === open(infilename, 'r') #print "# Read file from: %s\n\n" % infilename else: infile === sys.stdin parsefile(uid) </nowiki></pre> === Make === Make参考资源: * info make * make(1) * ''Managing Projects with make'', 2nd edition (O'Reilly) 简单自动变量: 语法规则: <pre><nowiki> target: [ prerequisites ... ] [TAB] command1 [TAB] -command2 # ignore errors [TAB] @command3 # suppress echoing </nowiki></pre> 在此[TAB]代表一个TAB符。 在完成 make 变量代换后,shell将逐行进行解释。在行尾使用\可以续行。使用$$可将$加入到shell脚本的环境变量中。 适用于target和prerequisites的隐含的等价规则: <pre><nowiki> %: %.c header.h </nowiki></pre> or, <pre><nowiki> %.o: %.c header.h </nowiki></pre> 在此,target包含了%字符(确切地说是其中之一),%可匹配实际的target文件名中任何非空子串。prerequisites同样也使用%来显示它们的名字是如何关联到实际的target文件名的。 用'''Suffix rules'''方法来定义make的隐含规则(implicit rules)已经'''过时'''。GNU make因为兼容性的考虑仍支持它,但只要有可能就应该使用与之等价的模版规则(pattern rules): <pre><nowiki> old suffix rule --> new pattern rule .c: --> % : %.c .c.o: --> %.o: %.c </nowiki></pre> 上述规则所使用的自动变量: <pre><nowiki> foo.o: new1.c new2.c old1.c new3.c $@ ==== foo.o (target) $< ==== new1.c (first one) $? ==== new1.c new2.c new3.c (newer ones) $^ ==== new1.c new2.c old1.c new3.c (all) $* ==== `%' matched stem in the target pattern. </nowiki></pre> 变量参考: <pre><nowiki> foo1 :== bar # One-time expansion foo2 === bar # Recursive expansion foo3 +== bar # Append SRCS :== $(wildcard *.c) OBJS :== $(foo:c=o) OBJS :== $(foo:%.c=%.o) OBJS :== $(patsubst %.c,%.o,$(foo)) DIRS === $(dir directory/filename.ext) # Extracts "directory" $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ... </nowiki></pre> 执行make -p -f/dev/null可查看内部自动规则。 === C === 准备工作: <pre><nowiki> # apt-get install glibc-doc manpages-dev libc6-dev gcc </nowiki></pre> C参考资源: * info libc (C library function reference) * gcc(1) * each_C_library_function_name(3) * Kernighan & Ritchie, ''The C Programming Language'', 2nd edition (Prentice Hall). ==== 简单C编程(gcc) ==== 一个简单的例子,将example.c和库函数libm编译成可执行文件run_example: <pre><nowiki> $ cat > example.c << EOF #include <stdio.h> #include <math.h> #include <string.h> int main(int argc, char **argv, char **envp){ double x; char y[11]; x=sqrt(argc+7.5); strncpy(y, argv[0], 10); /* prevent buffer overflow */ y[10] === '\0'; /* fill to make sure string ends with '\0' */ printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]); return 0; } EOF $ gcc -Wall -g -o run_example example.c -lm $ ./run_example 1, 2.915, ./run_exam, (null) $ ./run_example 1234567890qwerty 2, 3.082, ./run_exam, 1234567890qwerty </nowiki></pre> 在此,sqrt() 链接库函数lib'''m'''需要-l'''m'''选项。真正的库函数是位于/lib/下的libm.so.6,它是libm-2.1.3.so的一个符号链接。 看看输出文本中最后的参数,尽管指定了%10s,它还是多于10个字符。 使用不带边界检查的指针内存操作函数如sprintf和strcpy会妨碍缓冲区溢出侦测,故使用snprintf和strncpy。 ==== 调试 ==== ===== 使用gdb进行调试 ===== 准备工作: <pre><nowiki> # apt-get install gdb </nowiki></pre> gdb参考资源: * info gdb (tutorial) * gdb(1) * http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html 使用-g选项编译程序就可使用gdb进行调试。许多命令都可以缩写。Tab扩展功能和在shell中的一样。 <pre><nowiki> $ gdb program (gdb) b 1 # 在line 1设置断点 (gdb) run arg1 arg2 arg3 # 运行程序 (gdb) next # 下一行 ... (gdb) step # 前进一步 ... (gdb) p parm # 打印parm ... (gdb) p parm=12 # 设置其值为12 </nowiki></pre> 在Emacs环境下调试程序,参阅 编辑器命令总汇(Emacs,Vim), 第 11.3.4 节。 Ubuntu 系统上所有默认安装的二进制文件都已经进行了 strip 操作, 调试符号已经被移除。 为了能够让 gdb 对 Ubuntu 软件包进行调试, 相关的软件包需要使用下面的方法重新打包: * 编辑 debian/control 来改变软件包的 [http://www.debian.org/doc/debian-policy/ch-controlfields#s-f-Version 版本]。 * 检查打包脚本,确保使用 CFLAGS=-g-Wall 来编译二进制文件。 * 设置 DEB_BUILD_OPTIONS=nostrip,noopt 来建立 Debian 包。 更多信息请参阅: [http://www.debian.org/doc/debian-policy/ch-files#s10.1 Policy 10.1]。 ===== 检查库函数关联关系 ===== 使用ldd可查看程序与库函数的关联关系: <pre><nowiki> $ ldd /bin/ls librt.so.1 ==> /lib/librt.so.1 (0x4001e000) libc.so.6 ==> /lib/libc.so.6 (0x40030000) libpthread.so.0 ==> /lib/libpthread.so.0 (0x40153000) /lib/ld-linux.so.2 ==> /lib/ld-linux.so.2 (0x40000000) </nowiki></pre> 可在chrooted环境下使用ls检查上述库函数在你的chroot环境中是否可见。 下面的命令也很有用: * strace: 跟踪系统调用和消息 * ltrace: 跟踪库函数调用 ===== 使用内存查漏工具进行调试 ===== Ubuntu 中有几个内存查漏工具。 * njamd * valgrind * dmalloc * electric-fence * memprof * memwatch (没有软件包,从 [http://directory.fsf.org/devel/debug/memwatch.html memwatch] 获取。) * mpatrol * leaktracer * libgc6 * 来自 [http://www.parasoft.com/ Parasoft] 的 Insure++(非自由软件,商业付费) 亦可查阅[http://www.cs.colorado.edu/homes/zorn/public_html/MallocDebug.html Debugging Tools for Dynamic Storage Allocation and Memory Management]. ==== Flex – 更好的Lex ==== flex是一个快速的词法分析机生成器。 flex参考资源: * info flex (教程) * flex(1) 需要提供你自己的main()或yywrap(),或者你的 program.l 象这样不带library编译(yywrap是一个宏;%option main隐含地打开了%option noyywrap): <pre><nowiki> %option main %% .|\n ECHO ; %% </nowiki></pre> 另外,还可以在cc命令行末尾加上-lfl链接选项进行编译(象AT&T-Lex使用-ll一样),此时就不需要%option了。 ==== Bison – 更好的Yacc ==== Ubuntu 中有几个软件包提供了与Yacc兼容的LALR词法生成器: * bison: GNU LALR parser generator * byacc: The Berkeley LALR parser generator * btyacc: Backtracking parser generator based on byacc bison参考资源: * info bison (教程) * bison(1) 需要提供自己的main()和yyerror()。main()调用yyparse(),而yyparse()调用yylex(),通常由FleX创建。 <pre><nowiki> %% %% </nowiki></pre> ==== Autoconf ==== autoconf一个shell脚本生成工具,由它生成的脚本能自动配置软件源码包,以适用于各种使用全套GNU build系统的类UNIX系统。 autoconf会生成配置脚本configure。configure使用 Makefile.in模版自动创建自定义Makefile。 ===== 编译并安装程序 ===== Ubuntu 不会改动/usr/local/下的文件(参阅 多样性支持, 第 2.5 节)。所以如果是从源码编译程序,并将其安装到/usr/local/下,是不会影响到Debian的。 <pre><nowiki> $ cd src $ ./configure --prefix=/usr/local $ make $ make install # this puts the files in the system </nowiki></pre> ===== 卸载程序 ===== 如果仍保存有源码,对其使用了autoconf/automake,并且记得是如何进行配置的: <pre><nowiki> $ ./configure all-of-the-options-you-gave-it # make uninstall </nowiki></pre> 另一种方法是,如果可以确定安装过程将文件都放在了/usr/local/,并且该目录下没有什么别的重要文件,可用下面的命令将其全部删除: <pre><nowiki> # find /usr/local -type f -print0 | xargs -0 rm -f </nowiki></pre> 如果不能确定文件安装到什么位置,最好使用checkinstall,该命令可提供明确的卸载路径。 === Web === 通过下面的方法来制作一个基本的交互动态网页: * 使用 HTML 表单在浏览器里显示查询。 * 填写和点击表单提交,将从浏览器传送一个将参数 编码的 URL 到服务器。例如: ** http://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3 ** http://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3 ** http://www.foo.dom/program.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3 * 在 web 服务器上的 CGI 程序(任何一个 program.* 程序) 将接受编码的 "VAR1=VAL1 VAR2=VAL2 VAR3=VAL3" 参数作为环境变量 “QUERY_STRING” 的内容,并执行该环境变量。 * CGI 程序的标准输出 将作为一个交互动态网页输出到 web 浏览器。 出于安全的考虑,最好不要手工写新的程序来分析 CGI 参数。 在 Perl (参阅 Perl, 第 13.4 节)、Python (参阅 Python, 第 13.5 节) 和 [http://www.php.net/ PHP] 中,有即定的模块具备这些功能。 当需要在客户端存储数据的时候,使用 cookies。 当需要在客户端进行数据处理的时候,经常使用 javascript。 更多信息,请参阅 [http://hoohoo.ncsa.uiuc.edu/cgi/ The Common Gateway Interface]、[http://www.apache.org/ The Apache Software Foundation] 和 [http://www.mozilla.org/js/ JavaScript]。 在浏览器地址栏里面直接输入编码的 URL http://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial,可以在 Google 搜索 “CGI tutorial”。 这也是一个查看 CGI 脚本在 Google 服务器上执行的好方法。 === 准备文档 === ==== roff排版 ==== 传统上,roff是主要的Unix文字处理系统。 参阅roff(7)、groff(7)、groff(1)、grotty(1)、troff(1)、groff_mdoc(7)、groff_man(7)、groff_ms(7)、groff_me(7)、groff_mm(7)以及info groff。 -me宏提供了一个不错了说明文档。如果使用的是groff(1.18或更新的版本),找到/usr/share/doc/groff/meintro.me.gz并执行下面的命令: <pre><nowiki> $ zcat /usr/share/doc/groff/meintro.me.gz | \ groff -Tascii -me - | less -R </nowiki></pre> 下面的命令将生成一个完整的纯文本文件: <pre><nowiki> $ zcat /usr/share/doc/groff/meintro.me.gz | \ GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > meintro.txt </nowiki></pre> 如果想打印出来,可使用PostScript输出: <pre><nowiki> $ groff -Tps meintro.txt | lpr $ groff -Tps meintro.txt | mpage -2 | lpr </nowiki></pre> ==== SGML ==== 准备工作: <pre><nowiki> # apt-get install debiandoc-sgml debiandoc-sgml-doc </nowiki></pre> debiandoc-sgml参考资源: * /usr/share/doc/debiandoc-sgml-doc * debiandoc-sgml(1) * ''[http://qref.sourceforge.net/usr/share/doc/docbook-defguide/html/docbook.html DocBook: The Definitive Guide]'',作者 Walsh 和 Muellner,(O'Reilly 出版社) (docbook-defguide 软件包) SGML能管理多种格式的文档。更简单的SGML系统是Debiandoc,本文档就使用到它完成的。只需对原始的文本文件的下列字符进行少许转换: * "<" --> < * ">" --> > * " " --> (非中断空格) * "&" --> & * "%" --> % * "(c)" --> © * "–" --> – * "—" --> — 设置章节为非打印注释,输入: <pre><nowiki> <!-- State issue here ... --> </nowiki></pre> 设置章节为可控注释,输入: <pre><nowiki> <![ %FIXME; [ State issue here ... ]]> </nowiki></pre> 在SGML中,仅条目的''首次声明''(first definition)有效。例如: <pre><nowiki> <!entity % qref "INCLUDE"> <![ %qref; [ <!entity param "Data 1"> ]]> <!entity param "Data 2"> ¶m; </nowiki></pre> 最终结果是“Data 1”。如果第一行使用“IGNORE”而非“INCLUDE”,则最终结果为“Data 2”(第二行是一个候选声明)。同样,重复出现的短语可分别提前在文档中定义。 <pre><nowiki> <!entity whoisthis "my"> Hello &whoisthis; friend. This is &whoisthis; book. </nowiki></pre> 该定义的结果如下: <pre><nowiki> Hello my friend. This is my book. </nowiki></pre> 可参阅 examples 目录中简短的SGML样例文件sample.sgml。 当 SGML 文档逐渐变大时,作为后端文本处理器使用的 TeX 偶尔会错误。 参阅 TeX/LaTeX, 第 13.9.3 节。 ==== TeX/LaTeX ==== 准备: <pre><nowiki> # tasksel # select Miscellaneous --> TeX/LaTeX environment </nowiki></pre> LaTeX 参考: * [http://www.tldp.org/HOWTO/TeTeX-HOWTO.html The teTeX HOWTO: The Linux-teTeX Local Guide] * tex(1) * latex(1) * ''The TeXbook'', by Donald E. Knuth, (Addison-Wesley) [[http://qref.sourceforge.net/quick/footnotes.zh-cn.html#f66 66]] * ''LaTeX - A Document Preparation System'', by Leslie Lamport, (Addison-Wesley) * ''The LaTeX Companion'', by Goossens, Mittelbach, Samarin, (Addison-Wesley) 这是一个很强大的排字环境。许多 SGML 处理器使用 LaTeX 作为他们的后端文本处理器。 由 lyx、lyx-xforms和 lyx-qt 提供的 Lyx,以及由 texmacs 提供的 GNU TeXmacs 为 LaTeX 提供了一个好的“所见及所得”的编辑环境,然而,许多人选择使用 Emacs 和 Vim 作为源代码编辑器。 有许多在线资源存在: * [http://qref.sourceforge.net/usr/share/doc/texmf/newhelpindex.html teTeX - A Documentation Guide] (tetex-doc 软件包) * [http://www.msu.edu/user/pfaffben/writings/ A Quick Introduction to LaTeX] * [http://www.stat.rice.edu/~helpdesk/howto/lyxguide.html A Simple Guide to Latex/Lyx] * [http://www-h.eng.cam.ac.uk/help/tpl/textprocessing/latex_basic/latex_basic.html Word Processing Using LaTeX] * [http://supportweb.cs.bham.ac.uk/documentation/LaTeX/lguide/local-guide/local-guide.html Local User Guide to teTeX/LaTeX] 当SGML文档不断增大后,TeX偶尔会出错。可通过修改/etc/texmf/texmf.cnf,增加缓冲池的容量来解决这个问题(更好的方法是编辑/etc/texmf/texmf.d/95NonPath然后运行update-texmf)。 ==== 文学编程 ==== 有文学的程序员书写包含代码的文档来代替包含文档的代码。 这种方法确保程序有一个好的文档。 关于文学编程的更多信息,参阅 [http://www.literateprogramming.com/ Literate Programming]。 ===== Noweb ===== 准备: <pre><nowiki> # apt-get install nowebm </nowiki></pre> Noweb 参考: * [http://www.eecs.harvard.edu/~nr/noweb/ Noweb --- A Simple, Extensible Tool for Literate Programming] * noweb(1) 这是一个类 WEB 的文学编程工具,独立于编程语言。由于提供了扩展而更简单。 [[http://qref.sourceforge.net/quick/footnotes.zh-cn.html#f67 67]] 当 noweb 被调用的时候,它将程序的源代码输出到在 noweb 中提到的文件中,它还将创建一个用于文档排版的 TeX 文件。 Ubuntu ifupdown 软件包是一个很好的例子。 <pre><nowiki> $ apt-get source ifupdown $ cd ifupdown* $ make ifupdown.pdf ifupdown.ps </nowiki></pre> ===== Doxygen ===== 准备: <pre><nowiki> # apt-get install doxygen doxygen-doc doxygen-gui </nowiki></pre> Doxygen 参考(由 doxygen 创建): * [http://www.doxygen.org/ Homepage] * [http://qref.sourceforge.net/usr/share/doc/doxygen-doc/html/index.html /usr/share/doc/doxygen-doc/html/index.html] 它能够为 C++、C、 Java、 IDL 和某些范围的 PHP 和 C# 程序产生 HTML、 RTF、 Unix 手册页、 PostScript 和 PDF(使用 LaTeX)文档。 Doxygen 与 JavaDoc (1.1)、 Qt-Doc 和 KDOC 兼容,它有特定的设计用来与用 Troll Tech 的 [http://www.trolltech.no/qt/ Qt] 工具包制作的项目兼容。 他甚至可以为没有文档的程序创建从属图、协作图和图形化的类分层图。输出类似于 Qt 的文档。 === 打包 === 准备工作: <pre><nowiki> # apt-get install debian-policy developers-reference \ maint-guide dh-make debhelper # apt-get install packaging-manual # if Potato </nowiki></pre> 有关打包的参考资源: * Ubuntu 软件包管理系统, 第 2.2 节 (basics) * Debian New Maintainers' Guide (tutorial) * dh-make(1) * Debian Developer's Reference (best practice) * Debian Policy Manual (authoritative) * Packaging Manual (Potato) ==== 单个二进制文件打包 ==== Joey Hess的快速和粗糙的打包法:生成一个单独的二进制包 <pre><nowiki> # mkdir -p mypkg/usr/bin mypkg/DEBIAN # cp binary mypkg/usr/bin # cat > mypkg/DEBIAN/control Package: mypackage Version: 1 Architecture: i386 Maintainer: Joey Hess <joeyh@debian.org> Description: my little package Don't expect much. ^D # dpkg-deb -b mypkg </nowiki></pre> ==== 使用工具打包 ==== 使用dh_make软件包中的dh-make工具创建一个基线包,接着按照dh-make(1)中描述的方法打包。会用到debian/rules中的debhelper。 一个较老的方法是使用debmake软件包中的deb-make。不需要debhelper脚本,仅需要shell环境。请不要再使用这种方法。 有关多种源码包的例子,参阅“mc”(dpkg-source -x mc_4.5.54.dsc),其中用到Adam Heath( doogie@debian.org )的“sys-build.mk”以及“glibc”(dpkg-source -x glibc_2.2.4-1.dsc)它由后来的Joel Klecker( espy@debian.org )所写的另一个系统打包。 [[Category:Ubuntu_参考手册]] [[Category:程序开发]]
该页面使用的模板:
模板:UbuntuManual
(
查看源代码
)
返回至
UbuntuManual:编程
。