目录
这里我给出一些 Debian 系统中的信息,帮助学习编程的人找出打包的源代码。下面是值得关注的软件包和与之对应的文档。
表 12.1. 帮助编程的软件包清单
软件包 | 流行度 | 大小 | 包 |
---|---|---|---|
autoconf
|
V:34, I:255 | 1868 |
由 autoconf-doc 包提供的“info autoconf ”
|
automake
|
V:33, I:250 | 1710 |
由 automake1.10-doc 包提供的“info automake ”
|
bash
|
V:848, I:999 | 5798 |
由 bash-doc 包提供的“info bash ”
|
bison
|
V:10, I:110 | 2061 |
由 bison-doc 包提供的“info bison ”
|
cpp
|
V:402, I:800 | 42 |
由 cpp-doc 包提供的“info cpp ”
|
ddd
|
V:0, I:12 | 3965 |
由 ddd-doc 包提供的“info ddd ”
|
exuberant-ctags
|
V:7, I:42 | 333 | exuberant-ctags(1) |
flex
|
V:9, I:99 | 1174 |
由 flex-doc 包提供的“info flex ”
|
gawk
|
V:402, I:506 | 2199 |
由 gawk-doc 包提供的“info gawk ”
|
gcc
|
V:189, I:605 | 45 |
由 gcc-doc 包提供的“info gcc ”
|
gdb
|
V:19, I:133 | 7928 |
由 gdb-doc 包提供的“info gdb ”
|
gettext
|
V:66, I:361 | 6496 |
由 gettext-doc 包提供的“info gettext ”
|
gfortran
|
V:7, I:65 | 16 |
由 gfortran-doc 包提供的“info
gfortran ”(Fortran 95)
|
fpc
|
I:4 | 119 119 | fpc(1)
和由 fp-docs 包提供的 html 文档(Pascal)
|
glade
|
V:1, I:10 | 2261 | 通过 UI Builder 菜单提供的文档 |
libc6
|
V:939, I:999 | 11065 |
通过 glibc-doc 和 glibc-doc-reference
提供的“info libc ”
|
make
|
V:185, I:612 | 1211 |
通过 make-doc 包提供的“info make ”
|
xutils-dev
|
V:1, I:16 | 1466 | imake(1),xmkmf(1) 等。 |
mawk
|
V:357, I:997 | 183 | mawk(1) |
perl
|
V:555, I:995 | 568 | perl(1)
以及通过 perl-doc 和 perl-doc-html 提供的 html
文档
|
python
|
V:617, I:987 | 624 | python(1)
以及通过 python-doc 包提供的 html 文档 |
tcl
|
V:29, I:434 | 21 | tcl(3)
以及通过 tcl-doc 包提供的更详细的手册页文档 |
tk
|
V:30, I:422 | 21 | tk(3)
以及通过 tk-doc 包提供的更详细的手册页文档 |
ruby
|
V:149, I:340 | 38 | ruby(1)
以及通过 ri 包提供的交互式参考手册 |
vim
|
V:117, I:396 | 2507 |
通过 vim-doc 包提供的帮助(F1)菜单
|
susv2
|
I:0 | 15 | 通过“单一UNIX规范(版本2)”获取(英语文档) |
susv3
|
I:0 | 15 | 通过“单一UNIX规范(版本3)”获取(英语文档) |
安装 manpages
和 manpages-dev
包之后,可以通过运行“man 名称
”查看手册页中的参考信息。安装了 GNU
工具的相关文档包之后,可以通过运行“info 程序名称
”查看参考文档。某些 GFDL 协议的文档与 DFSG
并不兼容,所以你可能需要在 main
仓库中包含 contrib
和
non-free
才能下载并安装它们。
![]() |
警告 |
---|---|
不要用“ |
![]() |
小心 |
---|---|
你可以把从源代码编译得到的程序直接放到“ |
![]() |
提示 |
---|---|
“歌曲:99瓶啤酒”的代码示例可以给你提供实践各种语言的好范本。 |
Shell 脚本 是指包含有下面格式的可执行的文本文件。
#!/bin/sh …… 命令
第一行指明了读取并执行这个文件的 shell 解释器。
读懂 shell 脚本的最好 办法是先理解类 UNIX 系统是如何工作的。这里有一些 shell 编程的提示。看看“Shell 错误”(http://www.greenend.org.uk/rjk/2001/04/shell.html),可以从错误中学习。
不像 shell 交互模式(参见第 1.5 节 “简单 shell 命令” 和 第 1.6 节 “类 Unix 的文本处理”),shell 脚本会频繁使用参数、条件和循环等。
系统中的许多脚本都可以通过任意 POSIX shell(参见 表 1.13 “shell 程序列表”)来执行。系统的默认 shell
是“/bin/sh
”,它是某个实际 shell 程序的链接。
对 lenny
或更老的系统来说,它是
bash(1)
对 squeeze
或更新的系统来说,它是
dash(1)
避免编写具有 bashisms(bash 化)或者 zshisms(zsh 化)语法的 shell 脚本,确保脚本在所有 POSIX shell 之间具有可移植性。你可以使用 checkbashisms(1) 对其进行检查。
表 12.2. 典型 bashism 语法列表
好的:POSIX | 应该避免的:bashism |
---|---|
if [ "$foo" = "$bar" ] ; then …
|
if [ "$foo" == "$bar" ] ; then …
|
diff -u file.c.orig file.c
|
diff -u file.c{.orig,}
|
mkdir /foobar /foobaz
|
mkdir /foo{bar,baz}
|
funcname() { … }
|
function funcname() { … }
|
八进制格式:"\377 "
|
十六进制格式:"\xff "
|
使用 "echo
" 命令的时候需要注意以下几个方面,因为根据内置 shell 和外部命令的不同,它的实现也有差别。
避免使用除“-n
”以外的任何命令行选项。
避免在字符串中使用转义序列,因为根据 shell 不同,计算后的结果也不一样。
![]() |
注意 |
---|---|
尽管“ |
![]() |
提示 |
---|---|
如果你想要在输出字符串中嵌入转义序列,用 " |
特殊的 shell 参数经常在 shell 脚本里面被用到。
表 12.3. shell 参数列表
shell 参数 | 值 |
---|---|
$0
|
shell 或 shell 脚本的名称 |
$1
|
第一个 shell 参数 |
$9
|
第 9 个 shell 参数 |
$#
|
位置参数数量 |
"$*"
|
"$1 $2 $3 $4 … "
|
"$@"
|
"$1" "$2" "$3" "$4" …
|
$?
|
最近一次命令的退出状态码 |
$$
|
这个 shell 脚本的 PID |
$!
|
最近开始的后台任务 PID |
如下所示是需要记忆的基本的参数展开。
表 12.4. shell 参数展开列表
参数表达式形式 |
如果 var 变量已设置那么值为
|
如果 var 变量没有被设置那么值为
|
---|---|---|
${var:-string}
|
"$var "
|
"string "
|
${var:+string}
|
"string "
|
"null "
|
${var:=string}
|
"$var "
|
"string " (并运行 "var=string ")
|
${var:?string}
|
"$var "
|
在 stderr 中显示 "string "
(出错退出)
|
以上这些操作中 ":
" 实际上都是可选的。
有 ":
" 等于测试的 var
值是存在且非空
没有 ":
" 等于测试的 var
值只是存在的,可以为空
表 12.5. 重要的 shell 参数替换列表
参数替换形式 | 结果 |
---|---|
${var%suffix}
|
删除位于 var 结尾的 suffix 最小匹配模式 |
${var%%suffix}
|
删除位于 var 结尾的 suffix 最大匹配模式 |
${var#prefix}
|
删除位于 var 开头的 prefix 最小匹配模式 |
${var##prefix}
|
删除位于 var 开头的 prefix 最大匹配模式 |
每个命令都会返回 退出状态,这可以被条件语句使用。
成功:0 ("True")
失败:非0 ("False")
![]() |
注意 |
---|---|
"0" 在 shell 条件语句中的意思是 "True",然而 "0" 在 C 条件语句中的含义为 "False"。 |
![]() |
注意 |
---|---|
" |
如下所示是需要记忆的基础 条件语法。
"<command> && <if_success_run_this_command_too>
|| true
"
"<command> || <if_not_success_run_this_command_too> ||
true
"
如下所示是多行脚本片段
if [ <conditional_expression> ]; then <if_success_run_this_command> else <if_not_success_run_this_command> fi
这里末尾的“|| true
”是需要的,它可以保证这个 shell
脚本在不小心使用了“-e
”选项而被调用时不会在该行意外地退出。
表 12.6. 在条件表达式中进行文件比较
表达式 | 返回逻辑真所需的条件 |
---|---|
-e <file>
|
<file> 存在 |
-d <file>
|
<file> 存在并且是一个目录 |
-f <file>
|
<file> 存在并且是一个普通文件 |
-w <file>
|
<file> 存在并且可写 |
-x <file>
|
<file> 存在并且可执行 |
<file1> -nt <file2>
|
<file1> 是否比 <file2> 新 |
<file1> -ot <file2>
|
<file1> 是否比 <file2> 旧 |
<file1> -ef <file2>
|
<file1> 和 <file2> 位于相同的设备上并且有相同的 inode 编号 |
表 12.7. 在条件表达式中进行字符串比较
表达式 | 返回逻辑真所需的条件 |
---|---|
-z <str>
|
<str> 的长度为零 |
-n <str>
|
<str> 的长度不为零 |
<str1> = <str2>
|
<str1> 和 <str2> 相等 |
<str1> != <str2>
|
<str1> 和 <str2> 不相等 |
<str1> < <str2>
|
<str1> 排列在 <str2> 之前(取决于语言环境) |
<str1> > <str2>
|
<str1> 排列在 <str2> 之后(取决于语言环境) |
算术整数的比较在条件表达式中为
"-eq
","-ne
","-lt
","-le
","-gt
"
和 "-ge
"。
这里有几种可用于 POSIX shell 的循环形式。
"for x in foo1 foo2 … ; do command ; done
",该循环会将
"foo1 foo2 …
" 赋予变量 "x
" 并执行
"command
"。
"while condition ; do command ; done
",当
"condition
" 为真时,会重复执行 "command
"。
"until condition ; do command ; done
",当
"condition
" 为假时,会重复执行 "command
"。
"break
" 可以用来退出循环。
"continue
" 可以用来重新开始下一次循环。
![]() |
提示 |
---|---|
C 语言中的数值迭代可以用
seq(1)
实现来生成 " |
![]() |
提示 |
---|---|
shell 大致以下列的顺序来处理一个脚本。
shell 读取一行。
如果该行包含有"…"
或 '…'
,shell 对该行各部分进行分组作为
一个标识(one token) (译注:one token 是指 shell
识别的一个结构单元).
shell 通过下列方式将行中的其它部分分隔进 标识(tokens)。
空白字符:<空格> <tab> <换行符>
元字符:< > | ; & ( )
shell 会检查每一个不位于 "…"
或 '...'
的 token 中的
保留字 来调整它的行为。
保留字:if then elif else fi for in
while unless do done case esac
shell 展开不位于 "…"
或 '...'
中的 别名。
shell 展开不位于 "…"
或 '...'
中的 波浪线。
"~
" → 当前用户的家目录
"~<user>
" → <user>
的家目录
shell 将不位于 '...'
中的 变量
展开为它的值。
变量:"$PARAMETER
" 或
"${PARAMETER}
"
shell 展开不位于 '...'
中的 命令替换。
"$( command )
" → "command
" 的输出
"` command `
" → "command
" 的输出
shell 将不位于 "…"
或 '...'
中的 glob 路径 展开为匹配的文件名。
*
→ 任何字符
?
→ 一个字符
[…]
→ 任何位于 "…
" 中的字符
shell 从下列几方面查找 命令 并执行。
函数 定义
内建命令
“$PATH
” 中的可执行文件
shell 前往下一行,并按照这个顺序从头再次进行处理。
双引号中的单引号是没有效果的。
在 shell 中执行 “set -x
” 或使用 “-x
” 选项启动
shell 可以让 shell 显示出所有执行的命令。这对调试来说是非常方便的。
为了使你的 shell 程序在 Debian 系统上尽可能地具有可移植性,你应该只使用 必要的 软件包所提供的应用程序。
"aptitude search ~E
",列出 必要的 软件包。
"dpkg -L <package_name> |grep '/man/man.*/'
",列出
<package_name>
软件包所提供的 man 手册。
表 12.8. 包含用于 shell 脚本的小型应用程序的软件包
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
coreutils
|
V:886, I:999 | 15016 | GNU 核心工具 |
debianutils
|
V:938, I:999 | 213 | 用于 Debian 的各种工具 |
bsdmainutils
|
V:864, I:998 | 586 | 来自 FreeBSD 更多的工具集合 |
bsdutils
|
V:860, I:999 | 255 | 来自 4.4BSD-Lite 的基础工具 |
moreutils
|
V:4, I:22 | 201 | 额外的 Unix 工具 |
![]() |
提示 |
---|---|
尽管 |
一个简单的 shell 程序的用户界面中,echo
和 read
命令的交互性较为一般,你可以使用对话程序等来提升交互性。
表 12.9. 用户界面程序列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
x11-utils
|
V:247, I:635 | 637 | xmessage(1):在一个窗口中显示一条消息或疑问(X) |
whiptail
|
V:425, I:996 | 69 | 从 shell 脚本中显示用户友好的对话框(newt) |
dialog
|
V:21, I:138 | 1119 | 从 shell 脚本中显示用户友好的对话框(ncurses) |
zenity
|
V:99, I:411 | 364 | 从 shell 脚本中显示图形对话框(gtk2.0) |
ssft
|
V:0, I:0 | 75 | Shell 脚本前端工具 (zenity, kdialog, and 带有 gettext 的 dialog 封装) |
gettext
|
V:66, I:361 | 6496 |
“/usr/bin/gettext.sh ”:翻译信息
|
下面是一个简单的脚本,它通过 dvdisaster(1) 创建了带有 RS02 补充数据的 ISO 映像。
#!/bin/sh -e # gmkrs02 : Copyright (C) 2007 Osamu Aoki <osamu@debian.org>, Public Domain #set -x error_exit() { echo "$1" >&2 exit 1 } # Initialize variables DATA_ISO="$HOME/Desktop/iso-$$.img" LABEL=$(date +%Y%m%d-%H%M%S-%Z) if [ $# != 0 ] && [ -d "$1" ]; then DATA_SRC="$1" else # Select directory for creating ISO image from folder on desktop DATA_SRC=$(zenity --file-selection --directory \ --title="Select the directory tree root to create ISO image") \ || error_exit "Exit on directory selection" fi # Check size of archive xterm -T "Check size $DATA_SRC" -e du -s $DATA_SRC/* SIZE=$(($(du -s $DATA_SRC | awk '{print $1}')/1024)) if [ $SIZE -le 520 ] ; then zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="The data size is good for CD backup:\\n $SIZE MB" elif [ $SIZE -le 3500 ]; then zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="The data size is good for DVD backup :\\n $SIZE MB" else zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="The data size is too big to backup : $SIZE MB" error_exit "The data size is too big to backup :\\n $SIZE MB" fi # only xterm is sure to have working -e option # Create raw ISO image rm -f "$DATA_ISO" || true xterm -T "genisoimage $DATA_ISO" \ -e genisoimage -r -J -V "$LABEL" -o "$DATA_ISO" "$DATA_SRC" # Create RS02 supplemental redundancy xterm -T "dvdisaster $DATA_ISO" -e dvdisaster -i "$DATA_ISO" -mRS02 -c zenity --info --title="Dvdisaster RS02" --width 640 --height 400 \ --text="ISO/RS02 data ($SIZE MB) \\n created at: $DATA_ISO" # EOF
你可能想要在桌面创建一个启动器,其中的命令设置为类似 “/usr/local/bin/gmkrs02 %d
”
的形式。
Make 是一个维护程序组的工具。一旦执行
make(1),make
会读取规则文件
Makefile
,自从上次目标文件被修改后,如果目标文件依赖的相关文件发生了改变,那么就会更新目标文件,或者目标文件不存在,那么这些文件更新可能会同时发生。
规则文件的语法如下所示。
目标:[相关文件 ...] [TAB] 命令1 [TAB] -命令2 # 忽略错误 [TAB] @命令3 # 禁止回显
这里面的 "[TAB]
" 是一个 TAB 代码。每一行在进行变量替换以后会被 shell 解释。在行末使用
"\
" 来继续此脚本。使用 "$$
" 输入
"$
" 来获得 shell 脚本中的环境变量值。
目标跟相关文件也可以通过隐式规则给出,例如,如下所示。
%.o: %.c header.h
在这里,目标包含了 "%
" 字符 (只是它们中确切的某一个)。"%
"
字符能够匹配实际的目标文件中任意一个非空的子串。相关文件同样使用 "%
" 来表明它们是怎样与目标文件建立联系的。
运行 "make -p -f/dev/null
" 命令来查看内部自动化的规则。
你可以通过下列方法设置适当的环境来编译使用 C 编程语言编写的程序。
# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential
libc6-dev
软件包,即 GNU C 库,提供了 C 标准库,它包含了 C 编程语言所使用的头文件和库例程。
参考信息如下。
“info libc
”(C 库函数参考)
gcc(1)
和 “info gcc
”
each_C_library_function_name(3)
Kernighan & Ritchie,“C 程序设计语言”,第二版(Prentice Hall)
一个简单的例子 “example.c
” 可以通过如下方式和 “libm
”
库一起编译为可执行程序 “run_example
”。
$ 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
为了使用
sqrt(3),必须使用
“-lm
” 链接来自 libc6
软件包的库
“/usr/lib/libm.so
”。实际的库文件位于
“/lib/
”,文件名为 “libm.so.6
”,它是指向
“libm-2.7.so
” 的一个链接。
请看一下输出文本的最后一段。即使指定了 “%10s
”,它依旧超出了 10 个字符。
使用没有边界检查的指针内存操作函数,比如 sprintf(3) 和 strcpy(3), 是不建议使用,是为防止缓存溢出泄露而导致上面的溢出问题。请使用 snprintf(3) 和 strncpy(3) 来替代.
调试是程序中很重要的一部分。知道怎样去调试程序使得作为 Debian 使用者的你, 能够做出有意义的错误报告。
Debian 上原始的调试器是 gdb(1), 它能让你在程序执行的时候检查程序。
让我们通过如下所示的命令来安装 gdb
及其相关程序。
# apt-get install gdb gdb-doc build-essential devscripts
gdb
的好的教程由 "info gdb
" 提供或者可以在网上的其他地方找到。如下是用
gdb(1)
在"程序
"带有 "-g
" 选项编译的时候来产生调试信息。
$ gdb program (gdb) b 1 # 在第一行设置断点 (gdb) run args # 带参数运行程序 (gdb) next # 执行下一步 ... (gdb) step # 单步进入 ... (gdb) p parm # 打印 parm 的值 ... (gdb) p parm=12 # 把值设为 12 ... (gdb) quit
![]() |
提示 |
---|---|
许多 gdb(1) 命令都能被缩写。Tab 扩展跟在 shell 一样都能工作。 |
因为在 Debian 系统上默认所有已安装的二进制程序都是精简的,绝大多数的调试符号已经从常规的软件包中移除了。为了能用
gdb(1)
调试 Debian 软件包,相对应的 *-dbg
软件包或 *-dbgsym
软件包需要被安装 (例如 libc6
需要安装
libc6-dbg
,coreutils
需要安装
coreutils-dbgsym
)。
老式的软件包将提供相应的 *-dbg
软件包。它将和原始软件包一起,直接放在 Debian main
档案库。对于新的软件包,当它们编译时,将会自动产生 *-dbgsym
软件包,那些调试软件包将被独立放在
debian-debug 档案库. 更多信息请参阅 Debian Wiki 文档 .
如果一个需要被调试的软件包没有提供其 *-dbg
软件包或 *-dbgsym
软件包,你需要按如下所示的从源代码中重构并且安装它。
$ mkdir /path/new ; cd /path/new $ sudo apt-get update $ sudo apt-get dist-upgrade $ sudo apt-get install fakeroot devscripts build-essential $ sudo apt-get build-dep source_package_name $ apt-get source package_name $ cd package_name*
按需修改 bug。
软件包调试版本跟它的官方 Debian 版本不冲突,例如当重新编译已存在的软件包版本产生的 "+debug1
"
后缀,如下所示是编译未发行的软件包版本产生的 "~pre1
" 后缀。
$ dch -i
如下所示编译并安装带有调试符号的软件包。
$ export DEB_BUILD_OPTIONS=nostrip,noopt $ debuild $ cd .. $ sudo debi package_name*.changes
你需要检查软件包的构建脚本并确保编译二进制的时候使用了 "CFLAGS=-g -Wall
" 选项。
当你碰到程序崩溃的时候,报告 bug 时附上栈帧信息是个不错的注意。
如下所示的步骤就可以取得栈帧信息。
在 gdb(1) 中运行程序。
重现崩溃。
它使得你重新回到 gdb
提示符。
在 gdb
提示符后输入 "bt
"。
程序在终端中的 gdb
环境运行时,如果它没反应,你可以按下
Ctrl-C
来中止程序来取得 gdb
提示符。
![]() |
提示 |
---|---|
通常,你会看到堆栈顶部有一行或者多行有 " |
$ MALLOC_CHECK_=2 gdb hello
表 12.12. 高级 gdb 命令列表
命令 | 命令用途的描述 |
---|---|
(gdb) thread apply all bt
|
得到多线程程序的所有线程栈帧 |
(gdb) bt full
|
查看函数调用栈中的参数信息 |
(gdb) thread apply all bt full
|
和前面的选项一起得到堆栈和参数 |
(gdb) thread apply all bt full 10
|
得到前10个调用的栈帧和参数信息,以此来去除不相关的输出 |
(gdb) set logging on
|
把 gdb 的日志输出到文件 (默认的是 "gdb.txt ")
|
如果一个 GNOME 程序 preview1
收到了一个 X 错误,您应当看见一条下面这样的信息。
'preview1' 程序出现 X 桌面系统错误。
如果就是这种情况,你可以尝试在运行程序的时候加上 "--sync
" 选项,并且在
"gdk_x_error
" 函数处设置中断来获得栈帧信息。
按如下所示使用 ldd(1) 来找出程序的库依赖性。
$ 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)
因为 ls(1) 运行在 `chroot`ed 环境,以上的库在 `chroot`ed 环境也必须是可用的。
Debian 上有一些可用的内存泄漏检测工具。
表 12.13. 内存泄漏检测工具的列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
libc6-dev
|
V:284, I:618 | 17379 | mtrace(1):调试 glibc 中的 malloc |
valgrind
|
V:8, I:55 | 72070 | 内存调试器和分析器 |
kmtrace
|
V:0, I:16 | 351 | 使用 glibc's matrace(1) 的 KDE 内存泄漏追踪器 |
alleyoop
|
V:0, I:1 | 655 | Valgrind 内存检查工具的 GNOME 前端 |
electric-fence
|
V:0, I:5 | 70 | malloc(e) 调试器 |
leaktracer
|
V:0, I:2 | 56 | C++ 程序内存泄露跟踪器 |
libdmalloc5
|
V:0, I:3 | 360 | 内存分配库调试 |
表 12.14. 静态代码分析工具的列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
splint
|
V:0, I:4 | 2239 | 静态检查 C 程序 bug 的工具 |
flawfinder
|
V:0, I:0 | 175 | 检查 C/C++ 源代码和查找安全漏洞的工具 |
perl
|
V:555, I:995 | 568 | 带有内部静态代码检测的解释器:B::Lint(3perl) |
pylint
|
V:6, I:16 | 988 | Python 代码静态检查器 |
weblint-perl
|
V:0, I:2 | 36 | 用于 HTML 的小巧的语法检查器 |
linklint
|
V:0, I:1 | 343 | 快速的网站维护工具及链接检查器 |
libxml2-utils
|
V:22, I:311 | 167 | 使用 xmllint(1) 来检查 XML 文件 |
可以使用 “info flex
” 查看
flex(1)
的教程。
你需要提供你自己的 "main()
" 和 "yywrap()
".否则,你的
flex 程序,看起来像这样的,编译的时候将不会带库。这是因为 "yywrap
" 是一个宏,
"%option main
" 隐性打开了 "%option
noyywrap
".
%option main %% .|\n ECHO ; %%
另外一种方法,在你的
cc(1)
命令行结尾,你可以使用编译链接器选项,"-lfl
"。(像使用 "-ll
" 的
AT&T-Lex ). 在这种情况下,不需要 "%option
".
在 Debian 里,有几个软件包提供 Yacc兼容的前瞻性的 LR 解析 或 LALR 解析的生成器。
表 12.15. 兼容 Yacc 的 LALR 解析器生成器列表
软件包 | 流行度 | 大小 | 说明 |
---|---|---|---|
bison
|
V:10, I:110 | 2061 | GNU LALR 解析器生成器 |
byacc
|
V:0, I:7 | 160 | 伯克利(Berkeley)LALR 解析器生成器 |
btyacc
|
V:0, I:0 | 207 |
基于 byacc 的回溯解析生成器
|
可以使用 “info bison
” 查看
bison(1)
的教程。
你需要提供你自己的的 "main()
" 和
"yyerror()
".通常,Flex 创建的 "main()
" 调用
"yyparse()
",它又调用了 "yylex()
".
%% %%
autoconf 是一种用于自动生成软件源代码包配置 shell 脚本的工具,以适应使用完整 GNU 构建系统的各种类 Unix 系统。
autoconf(1)
生成配置脚本 “configure
”。“configure
” 使用
“Makefile.in
” 模板自动生成一个自定义的 “Makefile
”。
![]() |
警告 |
---|---|
当你安装编译好的程序的时候,注意不要覆盖系统文件。 |
Debian 不会在 "/usr/local
" 或 "/opt
"
目录下创建文件。如果你想要源码编译程序,把它安装到 "/usr/local/
" 目录下,因为这并不会影响到
Debian。
$ cd src $ ./configure --prefix=/usr/local $ make $ make install # 这一步是把文件安装到系统上
如果你有源码并且它使用 autoconf(1)/automake(1),如果你能记得你是怎样配置它的话,执行如下的命令来卸载程序。
$ ./configure "all-of-the-options-you-gave-it" # make uninstall
或者,如果你十分确信安装进程把文件都放在了 "/usr/local/
"
下并且这里没什么重要的东西,你可以通过如下的命令来清除它所有的内容。
# find /usr/local -type f -print0 | xargs -0 rm -f
如果你不确定文件被安装到了哪里,你可以考虑使用 checkinstall
软件包中的
checkinstall(8),它将会提供一个清晰的卸载路径。现在,它支持创建带有
“-D
” 选项的 Debian 软件包。
虽然任何 AWK 脚本都可以通过 a2p(1) 转换成 Perl,但单行的 AWK 脚本最好还是手动转换为单行的 Perl 脚本。
让我们来看看下面这个 AWK 脚本片段。
awk '($2=="1957") { print $3 }' |
这等价于下列的任意一行。
perl -ne '@f=split; if ($f[1] eq "1957") { print "$f[2]\n"}' |
perl -ne 'if ((@f=split)[1] eq "1957") { print "$f[2]\n"}' |
perl -ne '@f=split; print $f[2] if ( $f[1]==1957 )' |
perl -lane 'print $F[2] if $F[1] eq "1957"' |
perl -lane 'print$F[2]if$F[1]eq+1957' |
最后一个简直就是个迷。它用上了下面列出的这些 Perl 的特性。
空格为可选项。
存在从数字到字符串的自动转换。
更多的命令行选项参见 perlrun(1)。想要更疯狂的 Perl 脚本,可以使用 Perl Golf。
基本的动态交互网页可由如下方法制作。
呈现给浏览器用户的是 HTML 形式。
填充并点击表单条目将会从浏览器向 web 服务器发送带有编码参数的下列 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
"
在 URL 里面 "%nn
" 是使用一个 16 进制字符的 nn
值代替。
环境变量设置为: "QUERY_STRING="VAR1=VAL1 VAR2=VAL2 VAR3=VAL3"
".
Web服务器上的CGI程序 (任何一个
"program.*
")在执行时,都会使用"$QUERY_STRING
"环境变量.
CGI 程序的 stdout
发送到浏览器,作为交互式的动态 web 页面展示。
出于安全考虑,最好不要自己从头编写解析CGI参数的手艺. 在Perl和Python中有现有的模块可以使用. PHP 中包含这些功能. 当需要客户端数据存储时, 可使用HTTP cookies . 当需要处理客户端数据时, 通常使用Javascript.
更多信息,参见 通用网关接口, Apache 软件基金会, 和 JavaScript.
直接在浏览器地址中输入 http://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial 就可以在 Google 上搜索 “CGI tutorial”。这是在 Google 服务器上查看 CGI 脚本运行的好方法。
如果你想制作一个 Debian 包,阅读下面内容。
第 2 章 Debian 软件包管理 理解基本的包管理系统
第 2.7.13 节 “移植一个软件包到 stable 系统” 理解基本的移植过程
第 9.10.4 节 “Chroot 系统” 理解基本的 chroot 技术
debuild(1), pbuilder(1) 和 pdebuild(1)
Debian 新维护者指引
作为一个教程(maint-guide
包)
Debian 开发者参考手册
(developers-reference
包)
Debian 策略手册
(debian-policy
包)
Debian 维护者指引
(debmake-doc
包)
debmake
, dh-make
,
dh-make-perl
等软件包,对软件包打包过程,也有帮助。