內容目錄
這裡我給出一些 Debian 系統中的資訊,幫助學習程式設計的人找出打包的原始碼。下面是值得關注的軟體包和與之對應的文件。
安裝 manpages
和 manpages-dev
包之後,可以通過運行“man 名稱
”查看手冊頁中的參考資訊。安裝了 GNU
工具的相關文檔包之後,可以通過運行“info 程序名稱
”查看參考文檔。某些 GFDL 協議的文檔與 DFSG
並不兼容,所以你可能需要在 main
倉庫中包含 contrib
和
non-free
才能下載並安裝它們。
請考慮使用版本控制系統工具。參見 節 10.5, “Git”。
![]() |
警告 |
---|---|
不要用“ |
![]() |
注意 |
---|---|
你可以把從源代碼編譯得到的程序直接放到“ |
![]() |
提示 |
---|---|
“歌曲:99瓶啤酒”的代碼示例可以給你提供實踐各種語言的好範本。 |
Shell 腳本 是指包含有下面格式的可執行的文本文件。
#!/bin/sh ... command lines
第一行指明瞭讀取並執行這個文件的 shell 解釋器。
讀懂 shell 指令碼的最好 辦法是先理解類 UNIX 系統是如何工作的。這裡有一些 shell 程式設計的提示。看看“Shell 錯誤”(https://www.greenend.org.uk/rjk/2001/04/shell.html),可以從錯誤中學習。
不像 shell 交互模式(參見節 1.5, “簡單 shell 指令” 和 節 1.6, “類 Unix 的文本處理”),shell 腳本會頻繁使用參數、條件和循環等。
系統中的許多指令碼都可以透過任意 POSIX shell(參見 表格 1.13, “shell 程式列表”)來執行。
預設的非互動 POSIX shell "/usr/bin/sh
" 是一個指向到
/usr/bin/dash
的符號連結,並被許多系統程式使用。
預設的互動式 POSIX shell 是 /usr/bin/bash
。
避免編寫具有 bashisms(bash 化)或者 zshisms(zsh 化)語法的 shell 指令碼,確保指令碼在所有 POSIX shell
之間具有可移植性。你可以使用 checkbashisms
(1) 對其進行檢查。
使用 "echo
" 指令的時候需要注意以下幾個方面,因為根據內建 shell 和外部指令的不同,它的實現也有差別。
避免使用除“-n
”以外的任何指令列選項。
避免在字串中使用轉義序列,因為根據 shell 不同,計算後的結果也不一樣。
![]() |
注意 |
---|---|
儘管“ |
![]() |
提示 |
---|---|
如果你想要在輸出字串中嵌入轉義序列,用 " |
特殊的 shell 參數經常在 shell 腳本里面被用到。
表格 12.2. shell 參數列表
shell 參數 | 值 |
---|---|
$0 |
shell 或 shell 指令碼的名稱 |
$1 |
第一個 shell 參數 |
$9 |
第 9 個 shell 參數 |
$# |
位置參數數量 |
"$*" |
"$1 $2 $3 $4 … " |
"$@" |
"$1" "$2" "$3" "$4" … |
$? |
最近一次指令的退出狀態碼 |
$$ |
這個 shell 指令碼的 PID |
$! |
最近開始的後臺任務 PID |
如下所示是需要記憶的基本的參數展開。
表格 12.3. 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.4. 重要的 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.5. 在條件表示式中進行檔案比較
表示式 | 回傳邏輯真所需的條件 |
---|---|
-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.6. 在條件表示式中進行字串比較
表示式 | 回傳邏輯真所需的條件 |
---|---|
-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 語言中的數值迭代可以用 |
![]() |
提示 |
---|---|
為了使你的 shell 程式在 Debian 系統上儘可能地具有可移植性,你應該只使用 必要的 軟體包所提供的應用程式。
"aptitude search ~E
",列出 必要的 軟體包。
"dpkg -L package_name |grep
'/man/man.*/'
",列出
package_name
軟體包所提供的 man 手冊。
表格 12.7. 包含用於 shell 指令碼的小型應用程式的軟體包
軟體包 | 流行度 | 大小 | 說明 |
---|---|---|---|
dash
|
V:884, I:997 | 191 | 小和快的 POSIX 相容 shell,用於 sh |
coreutils
|
V:880, I:999 | 18307 | GNU 核心工具 |
grep
|
V:782, I:999 | 1266 | GNU grep 、egrep 和
fgrep |
sed
|
V:790, I:999 | 987 | GNU sed |
mawk
|
V:442, I:997 | 285 | 小和快的 awk |
debianutils
|
V:907, I:999 | 224 | 用於 Debian 的各種工具 |
bsdutils
|
V:519, I:999 | 356 | 來自 4.4BSD-Lite 的基礎工具 |
bsdextrautils
|
V:596, I:713 | 339 | 來自 4.4BSD-Lite 的額外的工具 |
moreutils
|
V:15, I:38 | 231 | 額外的 Unix 工具 |
![]() |
提示 |
---|---|
儘管 |
參見 節 1.6, “類 Unix 的文本處理” 的例子。
表格 12.8. 直譯器相關軟體包列表
軟體包 | 流行度 | 大小 | 包 |
---|---|---|---|
dash
|
V:884, I:997 | 191 | sh: 小和快的 POSIX 相容的 shell,用於 sh |
bash
|
V:838, I:999 | 7175 | sh: 由 bash-doc
包提供的“info bash ” |
mawk
|
V:442, I:997 | 285 | AWK: 小和快的 awk |
gawk
|
V:285, I:349 | 2906 | AWK: 由 gawk-doc
包提供的“info gawk ” |
perl
|
V:707, I:989 | 673 | Perl: perl (1) 以及透過
perl-doc 和 perl-doc-html 提供的 html 文件 |
libterm-readline-gnu-perl
|
V:2, I:29 | 380 | GNU ReadLine/History 庫的 Perl 擴充套件: perlsh (1) |
libreply-perl
|
V:0, I:0 | 171 | Perl 的 REPL : reply (1) |
libdevel-repl-perl
|
V:0, I:0 | 237 | Perl 的 REPL : re.pl (1) |
python3
|
V:718, I:953 | 81 | Python: python3 (1) 以及透過
python3-doc 包提供的 html 文件 |
tcl
|
V:25, I:218 | 21 | Tcl: tcl (3) 以及透過
tcl-doc 包提供的更詳細的手冊頁文件 |
tk
|
V:20, I:211 | 21 | Tk:tk (3) 以及透過
tk-doc 包提供的更詳細的手冊頁文件 |
ruby
|
V:86, I:208 | 29 | Ruby: ruby (1),
erb (1), irb (1),
rdoc (1), ri (1) |
當你希望在 Debian 上自動化執行一個任務,你應當首先使用解釋性語言指令碼。選擇解釋性語言的準則是:
使用 dash
,如果任務是簡單的,使用 shell 程式聯合 CLI 命令列程式。
使用 python3
,如果任務不是簡單的,你從零開始寫。
使用
perl
、tcl
、ruby
……,如果在
Debian 上有用這些語言寫的現存程式碼,需要為完成任務進行調整。
如果最終程式碼太慢,為提升執行速度,你可以用編譯型語言重寫關鍵部分,從解釋性語言呼叫。
大部分直譯器提供基本的語法檢查和程式碼跟蹤功能。
“dash -n script.sh” - Shell 指令碼語法檢查
“dash -x script.sh” - 跟蹤一個 Shell 指令碼
“python -m py_compile script.py” - Python 指令碼語法檢查
“python -mtrace --trace script.py” - 跟蹤一個 Python 指令碼
“perl -I ../libpath -c script.pl” - Perl 指令碼語法檢查
“perl -d:Trace script.pl” - 跟蹤一個 Perl 指令碼
為測試 dash
程式碼,嘗試下 節 9.1.4, “Readline 封裝”,它提供了和 bash
類似的互動式環境。
為了測試 perl
程式碼,嘗試下 Perl 的 REPL 環境,它為 Perl 提供了 Python 類似的
REPL (=READ + EVAL + PRINT +
LOOP) 環境。
shell 指令碼能夠被改進用來製作一個吸引人的 GUI(圖形使用者介面)程式。技巧是用一個所謂的對話程式來代替使用
echo
和 read
命令的乏味互動。
表格 12.9. 對話(dialog )程式列表
軟體包 | 流行度 | 大小 | 說明 |
---|---|---|---|
x11-utils
|
V:192, I:566 | 651 | xmessage (1):在一個視窗中顯示一條訊息或疑問(X) |
whiptail
|
V:284, I:996 | 56 | 從 shell 指令碼中顯示使用者友好的對話方塊(newt) |
dialog
|
V:11, I:99 | 1227 | 從 shell 指令碼中顯示使用者友好的對話方塊(ncurses) |
zenity
|
V:76, I:363 | 183 | 從 shell 指令碼中顯示圖形對話方塊(GTK) |
ssft
|
V:0, I:0 | 75 | Shell 指令碼前端工具 (zenity, kdialog, and 帶有 gettext 的 dialog 封裝) |
gettext
|
V:56, I:259 | 5818 | “/usr/bin/gettext.sh ”:翻譯資訊 |
這裡是一個用來演示的 GUI 程式的例子,僅使用一個 shell 指令碼是多麼容易。
這個指令碼使用 zenity
來選擇一個檔案 (預設 /etc/motd
)
並顯示它。
這個指令碼的 GUI 啟動器能夠按 節 9.4.10, “從 GUI 啟動一個程式” 建立。
#!/bin/sh -e # Copyright (C) 2021 Osamu Aoki <osamu@debian.org>, Public Domain # vim:set sw=2 sts=2 et: DATA_FILE=$(zenity --file-selection --filename="/etc/motd" --title="Select a file to check") || \ ( echo "E: File selection error" >&2 ; exit 1 ) # Check size of archive if ( file -ib "$DATA_FILE" | grep -qe '^text/' ) ; then zenity --info --title="Check file: $DATA_FILE" --width 640 --height 400 \ --text="$(head -n 20 "$DATA_FILE")" else zenity --info --title="Check file: $DATA_FILE" --width 640 --height 400 \ --text="The data is MIME=$(file -ib "$DATA_FILE")" fi
這種使用 shell 指令碼的 GUI 程式方案只對簡單選擇的場景有用。如果你寫一個其它任何複雜的程式,請考慮在功能更強的平臺上寫。
GUI(圖形使用者介面)檔案管理器在選定的檔案上,能夠用外加的擴充套件軟體包來擴充套件執行一些常見行為。透過增加特定的指令碼,它們也能夠用來定製執行非常特殊的行為。
對於 KDE,參見 Creating Dolphin Service Menus。
對於 Xfce,參見 Thunar - Custom Actions 和 https://help.ubuntu.com/community/ThunarCustomActions。
對於 LXDE,參見 Custom Actions。
表格 12.10. 編譯相關軟體包列表
軟體包 | 流行度 | 大小 | 說明 |
---|---|---|---|
gcc
|
V:167, I:550 | 36 | GNU C 編譯器 |
libc6-dev
|
V:248, I:567 | 12053 | GNU C 庫:開發庫和標頭檔案 |
g++
|
V:56, I:501 | 13 | GNU C++ 編譯器 |
libstdc++-10-dev
|
V:14, I:165 | 17537 | GNU 標準 C++ 庫 版本 3(開發檔案) |
cpp
|
V:334, I:727 | 18 | GNU C 預處理 |
gettext
|
V:56, I:259 | 5818 | GNU 國際化工具 |
glade
|
V:0, I:5 | 1204 | GTK 使用者介面構建器 |
valac
|
V:0, I:4 | 725 | 使用 GObject 系統類似 C# 的語言 |
flex
|
V:7, I:73 | 1243 | LEX 相容的 fast lexical analyzer generator |
bison
|
V:7, I:80 | 3116 | YACC 相容的 解析器生成器 |
susv2
|
I:0 | 16 | 通過“單一UNIX規範(版本2)”獲得(英語文檔) |
susv3
|
I:0 | 16 | 通過“單一UNIX規範(版本3)”獲得(英語文檔) |
susv4
|
I:0 | 16 | 透過“單一UNIX規範(版本4)”獲取(英語文件) |
golang
|
I:20 | 11 | Go 程式語言編譯器 |
rustc
|
V:3, I:14 | 8860 | Rust 系統程式語言 |
haskell-platform
|
I:1 | 12 | 標準的 Haskell 庫和工具 |
gfortran
|
V:6, I:62 | 15 | GNU Fortran 95 編譯器 |
fpc
|
I:2 | 103 | 自由 Pascal |
這裡,包括了 節 12.3.3, “Flex — 一個更好的 Lex” 和 節 12.3.4, “Bison — 一個更好的 Yacc”,用來說明 類似編譯器的程式怎樣用C 語言來編寫,是透過編譯高階描述到 C 語言。
你可以通過下列方法設定適當的環境來編譯使用 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)
在 Debian 裡,有幾個軟體包提供 Yacc相容的前瞻性的 LR 解析 或 LALR 解析的生成器。
可以使用 “info bison
” 檢視 bison
(1) 的教學。
你需要提供你自己的的 "main()
" 和
"yyerror()
".通常,Flex 建立的 "main()
" 呼叫
"yyparse()
",它又呼叫了 "yylex()
".
這裡是一個建立簡單終端計算程式的例子。
讓我們建立 example.y
:
/* calculator source for bison */ %{ #include <stdio.h> extern int yylex(void); extern int yyerror(char *); %} /* declare tokens */ %token NUMBER %token OP_ADD OP_SUB OP_MUL OP_RGT OP_LFT OP_EQU %% calc: | calc exp OP_EQU { printf("Y: RESULT = %d\n", $2); } ; exp: factor | exp OP_ADD factor { $$ = $1 + $3; } | exp OP_SUB factor { $$ = $1 - $3; } ; factor: term | factor OP_MUL term { $$ = $1 * $3; } ; term: NUMBER | OP_LFT exp OP_RGT { $$ = $2; } ; %% int main(int argc, char **argv) { yyparse(); } int yyerror(char *s) { fprintf(stderr, "error: '%s'\n", s); }
讓我們建立 example.l
:
/* calculator source for flex */ %{ #include "example.tab.h" %} %% [0-9]+ { printf("L: NUMBER = %s\n", yytext); yylval = atoi(yytext); return NUMBER; } "+" { printf("L: OP_ADD\n"); return OP_ADD; } "-" { printf("L: OP_SUB\n"); return OP_SUB; } "*" { printf("L: OP_MUL\n"); return OP_MUL; } "(" { printf("L: OP_LFT\n"); return OP_LFT; } ")" { printf("L: OP_RGT\n"); return OP_RGT; } "=" { printf("L: OP_EQU\n"); return OP_EQU; } "exit" { printf("L: exit\n"); return YYEOF; } /* YYEOF = 0 */ . { /* ignore all other */ } %%
按下面的方法來從 shell 提示符執行來嘗試這個:
$ bison -d example.y $ flex example.l $ gcc -lfl example.tab.c lex.yy.c -o example $ ./example 1 + 2 * ( 3 + 1 ) = L: NUMBER = 1 L: OP_ADD L: NUMBER = 2 L: OP_MUL L: OP_LFT L: NUMBER = 3 L: OP_ADD L: NUMBER = 1 L: OP_RGT L: OP_EQU Y: RESULT = 9 exit L: exit
類似 Indent 的工具能夠幫助人進行程式碼檢查,透過一致性的重新格式化原始碼。
類似 Ctags 的工具能夠幫助人進行程式碼檢查,透過利用原始碼中發現的名字生成 索引(或標籤)檔案。
![]() |
提示 |
---|---|
配置你喜歡的編輯器( |
表格 12.12. 靜態程式碼分析工具的列表
軟體包 | 流行度 | 大小 | 說明 |
---|---|---|---|
vim-ale
|
I:0 | 2591 | 用於 Vim 8 和 NeoVim 的非同步 Lint 引擎 |
vim-syntastic
|
I:3 | 1379 | vim 語法檢查利器 |
elpa-flycheck
|
V:0, I:1 | 808 | Emacs 現代即時語法檢查 |
elpa-relint
|
V:0, I:0 | 147 | Emacs Lisp 正則錯誤發現器 |
cppcheck-gui
|
V:0, I:1 | 7224 | 靜態 C/C++ 程式碼分析工具(GUI) |
shellcheck
|
V:2, I:13 | 18987 | shell 指令碼的 lint 工具 |
pyflakes3
|
V:2, I:15 | 20 | Python 3 程式被動檢查器 |
pylint
|
V:4, I:20 | 2018 | Python 程式碼靜態檢查器 |
perl
|
V:707, I:989 | 673 | 帶有內部靜態程式碼檢測的直譯器:B::Lint (3perl) |
rubocop
|
V:0, I:0 | 3247 | Ruby 靜態程式碼分析器 |
clang-tidy
|
V:2, I:11 | 21 | 基於 clang 的 C++ 規則格式檢查工具 |
splint
|
V:0, I:2 | 2320 | 靜態檢查 C 程式 bug 的工具 |
flawfinder
|
V:0, I:0 | 205 | 檢查 C/C++ 原始碼和查詢安全漏洞的工具 |
black
|
V:3, I:13 | 660 | 強硬的 Python 程式碼格式化器 |
perltidy
|
V:0, I:4 | 2493 | Perl 指令碼縮排和重新格式化 |
indent
|
V:0, I:7 | 431 | C 語言原始碼格式化程式 |
astyle
|
V:0, I:2 | 785 | C、 C++、 Objective-C、 C# 和 Java 的原始碼縮排器 |
bcpp
|
V:0, I:0 | 111 | 美化 C(++) |
xmlindent
|
V:0, I:1 | 53 | XML 流 重新格式化 |
global
|
V:0, I:2 | 1908 | 原始碼檢索和瀏覽工具 |
exuberant-ctags
|
V:2, I:20 | 341 | 構建原始碼定義的標籤檔案索引 |
universal-ctags
|
V:1, I:11 | 3386 | 構建原始碼定義的標籤檔案索引 |
除錯是程式中很重要的一部分。知道怎樣去除錯程式,能夠讓你成為一個好的 Debian 使用者, 能夠做出有意義的錯誤報告。
Debian 上原始的偵錯程式是 gdb
(1),
它能讓你在程式執行的時候檢查程式。
讓我們通過如下所示的指令來安裝 gdb
及其相關程式。
# apt-get install gdb gdb-doc build-essential devscripts
好的 gdb
教程能夠被發現:
“info gdb
”
在 /usr/share/doc/gdb-doc/html/gdb/index.html
的 “Debugging
with GDB”
這裡是一個簡單的列子,用 gdb
(1) 在"程式
"帶有
"-g
" 選項編譯的時候來產生除錯資訊。
$ gdb program (gdb) b 1 # set break point at line 1 (gdb) run args # run program with args (gdb) next # next line ... (gdb) step # step forward ... (gdb) p parm # print parm ... (gdb) p parm=12 # set value to 12 ... (gdb) quit
![]() |
提示 |
---|---|
許多 |
Debian 系統在預設情況下,所有安裝的二進位制程式會被 stripped,因此大部分除錯符號(debugging
symbols)在通常的軟體包裡面會被移除。為了使用 gdb
(1) 除錯 Debian 軟體包,
*-dbgsym
軟體包需要被安裝。(例如,安裝
coreutils-dbgsym
,用於除錯coreutils
)原始碼軟體包和普通的二進位制軟體包一起自動生成
*-dbgsym
軟體包。那些除錯軟體包將被獨立放在 debian-debug 檔案庫。更多資訊請參閱 Debian Wiki 文件 。
如果一個需要被除錯的軟體包沒有提供其 *-dbgsym
軟體包,你需要按如下所示的從原始碼中重構並且安裝它。
$ mkdir /path/new ; cd /path/new $ sudo apt-get update $ sudo apt-get dist-upgrade $ sudo apt-get install fakeroot devscripts build-essential $ apt-get source package_name $ cd package_name* $ sudo apt-get build-dep ./
按需修改 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 執行程式。
崩潰程式。
在 GDB 提示符輸入 "bt
"。
先奔潰的方案:
更新“/etc/security/limits.conf”檔案,包括下面內容:
* soft core unlimited
shell 提示符下輸入 "ulimit -c unlimited
"。
從這個 shell 提示符執行程式。
載入 core dump 檔案到 GDB,用 "gdb gdb
./program_binary core
" 。
在 GDB 提示符輸入 "bt
"。
對於無限迴圈或者鍵盤凍結的情況,你可以透過按 Ctrl-\
或 Ctrl-C
或者執行 “kill -ABRT PID
” 強制奔潰程式。(參見
節 9.4.12, “殺死一個程序”)
![]() |
提示 |
---|---|
通常,你會看到堆疊頂部有一行或者多行有 " $ MALLOC_CHECK_=2 gdb hello |
表格 12.14. 高階 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 ") |
按如下所示使用 ldd
(1) 來找出程式的庫依賴性。
$ ldd /usr/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.15. 記憶體洩漏檢測工具的列表
軟體包 | 流行度 | 大小 | 說明 |
---|---|---|---|
libc6-dev
|
V:248, I:567 | 12053 | mtrace (1):除錯 glibc 中的 malloc |
valgrind
|
V:6, I:37 | 78191 | 記憶體偵錯程式和分析器 |
electric-fence
|
V:0, I:3 | 73 | malloc (e) 偵錯程式 |
libdmalloc5
|
V:0, I:2 | 390 | 記憶體分配庫除錯 |
duma
|
V:0, I:0 | 296 | 在 C 和 C++ 程式中檢測快取溢位和快取欠載( buffer under-runs )的庫 |
leaktracer
|
V:0, I:1 | 56 | C++ 程式記憶體洩露跟蹤器 |
你可以使用下面的方式通過 objdump
(1) 反編譯二進位制程式碼。
$ objdump -m i386 -b binary -D /usr/lib/grub/x86_64-pc/stage1
![]() |
注意 |
---|---|
|
表格 12.16. 編譯工具軟體包列表
軟體包 | 流行度 | 大小 | 包 |
---|---|---|---|
make
|
V:151, I:555 | 1592 | 通過 make-doc 包提供的“info make ” |
autoconf
|
V:31, I:230 | 2025 | 由 autoconf-doc 包提供的“info autoconf ” |
automake
|
V:30, I:228 | 1837 | 由 automake1.10-doc 包提供的“info automake ” |
libtool
|
V:25, I:212 | 1213 | 由 libtool-doc 包提供"info libtool " |
cmake
|
V:17, I:115 | 36607 | cmake (1) 跨平臺、開源的編譯系統 |
ninja-build
|
V:6, I:41 | 428 | ninja (1) 接近 Make 精髓的小編譯系統 |
meson
|
V:3, I:22 | 3759 | meson (1) 在 ninja 之上的高生產力的構建系統 |
xutils-dev
|
V:0, I:9 | 1484 | imake (1),xmkmf (1) 等。 |
Make 是一個維護程式組的工具。一旦執行
make
(1),make
會讀取規則檔案
Makefile
,自從上次目標檔案被修改後,如果目標檔案依賴的相關檔案發生了改變,那麼就會更新目標檔案,或者目標檔案不存在,那麼這些檔案更新可能會同時發生。
規則檔案的語法如下所示。
target: [ prerequisites ... ] [TAB] command1 [TAB] -command2 # ignore errors [TAB] @command3 # suppress echoing
這裡面的 "[TAB]
" 是一個 TAB 程式碼。每一行在進行變數替換以後會被 shell 解釋。在行末使用
"\
" 來繼續此指令碼。使用 "$$
" 輸入
"$
" 來獲得 shell 指令碼中的環境變數值。
目標跟相關檔案也可以通過隱式規則給出,例如,如下所示。
%.o: %.c header.h
在這裡,目標包含了 "%
" 字元 (只是它們中確切的某一個)。"%
"
字元能夠匹配實際的目標檔案中任意一個非空的子串。相關檔案同樣使用 "%
" 來表明它們是怎樣與目標檔案建立聯絡的。
執行 "make -p -f/dev/null
" 指令來檢視內部自動化的規則。
Autotools 是一套程式設計工具,旨在協助使原始碼包可移植到許多 類 Unix 系統。
如果你有原始碼並且它使用
autoconf
(1)/automake
(1),如果你能記得你是怎樣調配它的話,執行如下的指令來解除安裝程式。
$ ./configure all-of-the-options-you-gave-it
$ sudo make uninstall
或者,如果你十分確信安裝程序把檔案都放在了 "/usr/local/
"
下並且這裡沒什麼重要的東西,你可以通過如下的指令來清除它所有的內容。
# find /usr/local -type f -print0 | xargs -0 rm -f
如果你不確定檔案被安裝到了哪裡,你可以考慮使用 checkinstall
軟體包中的
checkinstall
(8),它將會提供一個清晰的解除安裝路徑。現在,它支援建立帶有
“-D
” 選項的 Debian 軟體包。
基本的動態互動網頁可由如下方法制作。
呈現給瀏覽器使用者的是 HTML 形式。
填充並點選表單條目將會從瀏覽器向 web 伺服器傳送帶有編碼參數的下列 URL 字串之一。
"https://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
"
"https://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
"
"https://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.
直接在瀏覽器地址中輸入 https://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.11.4, “Chroot 系統” 理解基本的 chroot 技術
debuild
(1) 和 sbuild
(1)
Debian 維護者指引
(debmake-doc
包)
Debian 開發者參考手冊
(developers-reference
包)
Debian 策略手冊
(debian-policy
包)
debmake
, dh-make
,
dh-make-perl
等軟體包,對軟體包打包過程,也有幫助。