查看“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 )所写的另一个系统打包。
该页面使用的模板:
模板:UbuntuManual
(
查看源代码
)
返回
UbuntuManual:编程
。
导航菜单
页面操作
页面
讨论
阅读
查看源代码
历史
页面操作
页面
讨论
更多
工具
个人工具
登录
导航
首页
最近更改
随机页面
页面分类
帮助
搜索
编辑
编辑指南
沙盒
新闻动态
字词处理
工具
链入页面
相关更改
特殊页面
页面信息