目次
Debian システム上でプログラミングを学ぶ人がパッケージ化されたソースコードを読み込めるようになるための指針を示します。以下はプログラムに関する特記すべきパッケージと対応する文書パッケージです。
オンラインリファレンスは manpages
と manpages-dev
パッケージをインストールした後で "man name
" とタイプすると利用可能です。GNU
ツールのオンラインリファレンスは該当する文書パッケージをインストールした後で "info
program_name
" とタイプすると使えます。一部の GFDL 文書は DFSG に準拠していないと考えられているので
main
アーカイブに加えて contrib
や
non-free
アーカイブを含める必要があるかもしれません。
バージョン コントロール システム ツールの使用を考えましょう。「Git」を参照下さい。
![]() |
警告 |
---|---|
" |
![]() |
注意 |
---|---|
ソースから直接コンパイルしたソフトウェアープログラムは、システムプログラムとかち合わないように、" |
![]() |
ヒント |
---|---|
"99ボトルのビールの歌" 作成のコード例はほとんど全てのプログラム言語に関する理解のための非常に好適です。 |
シェルスクリプトは実行ビットがセットされたテキストファイルで、以下に示すフォーマットのコマンドを含んでいます。
#!/bin/sh ... command lines
最初の行はこのファイル内容を読み実行するシェルインタープリタを指定します。
シェルスクリプトを読むのは Unix 的なシステムがどのように機能しているのかを理解する最良の方法です。ここでは、シェルプログラムに関する指針や心がけを記します。失敗から学ぶために "シェルの失敗" (https://www.greenend.org.uk/rjk/2001/04/shell.html) を参照下さい。
シェル対話モード (「シェルプロンプト」と「Unix 的テキスト処理」を参照下さい) と異なり、シェルスクリプトは変数や条件文やループを繁用します。
多くのシステムスクリプトは POSIX シェル (表1.13「シェルプログラムのリスト」を参照下さい) のどれで解釈されるか分かりません。
デフォールトの非インタラクティブなシェル "/usr/bin/sh
" は
/usr/bin/dash
をさしているシムリンクで、多くのシステムプログラムで使われます。
デフォルトのインタラクティブなシェルは /usr/bin/bash
です。
全ての POSIX シェル間でポータブルとするために bashisms や
zshisms
を使うシェルスクリプトを書くのを避けます。checkbashisms
(1) を使うとこれがチェックできます。
"echo
"
コマンドはその実装がシェルビルトインや外部コマンド間で相違しているので以下の注意点を守って使わなければいけません。
"-n
" 以外のどのコマンドオプション使用も避けます。
文字列中にエスケープシーケンスはその取扱いに相違があるので使用を避けます。
![]() |
注記 |
---|---|
" |
![]() |
ヒント |
---|---|
出力文字列にエスケープシーケンスを埋め込む必要がある場合には、" |
特別なシェルパラメーターがシェルスクリプト中ではよく使われます。
表12.2 シェル変数のリスト
シェル変数 | 変数値 |
---|---|
$0 |
シェルまたはシェルスクリプトの名前 |
$1 |
最初 (1番目) のシェル引数 |
$9 |
9番目のシェル引数 |
$# |
シェル引数の数 |
"$*" |
"$1 $2 $3 $4 … " |
"$@" |
"$1" "$2" "$3" "$4" … |
$? |
最新のコマンドの終了状態 |
$$ |
このシェルスクリプトの PID |
$! |
最近スタートしたバックグラウンドジョブの PID |
覚えておくべき基本的なパラメーター展開を次に記します。
表12.3 シェル変数展開のリスト
パラメーター式形 | var が設定されているときの値 |
var が設定されていないときの値 |
---|---|---|
${var:-string} |
"$var " |
"string " |
${var:+string} |
"string " |
"null " |
${var:=string} |
"$var " |
"string " (合わせて "var=string " を実行) |
${var:?string} |
"$var " |
"string " をstderr に出力
(エラーとともに exit する) |
ここで、これら全てのオペレーターのコロン ":
" は実際はオプションです。
":
" 付き = 演算子は存在と非ヌル文字列をテストします
":
" 無し = 演算子は存在のみをテストします
表12.4 重要なシェル変数置換のリスト
パラメーター置換形 | 結果 |
---|---|
${var%suffix} |
最短のサフィックスパターンを削除 |
${var%%suffix} |
最長のサフィックスパターンを削除 |
${var#prefix} |
最短のプレフィックスパターンを削除 |
${var##prefix} |
最長のプレフィックスパターンを削除 |
各コマンドは条件式に使えるエグジットステイタスを返します。
成功: 0 ("真")
エラー: 非0 ("偽")
![]() |
注記 |
---|---|
シェル条件文の文脈において "0" は "真" を意味しますが、C 条件文の文脈では "0" は "偽" を意味します。 |
![]() |
注記 |
---|---|
" |
覚えておくべき基本的な条件文の慣用句は次です。
"command &&
成功したらこのcommandも実行 || true
"
"command ||
もしcommandが成功しないとこのコマンドも実行 || true
"
以下のような複数行のスクリプト断片
if [ conditional_expression ]; then if_success_run_this_command else if_not_success_run_this_command fi
ここで、シェルが "-e
" フラグ付きで起動された際にシェルスクリプトがこの行で誤って exit
しないようにするために、末尾の "|| true
" が必要です。
表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 シェル中で使われるループの慣用句があります。
"for x in foo1 foo2 … ; do コマンド ; done
" は "foo1
foo2 …
" リストの項目を変数 "x
" に代入し
"コマンド
" を実行してループします。
"while 条件 ; do コマンド ; done
" は"条件
"
が真の場合 "コマンド
" を繰り返します。
"until 条件 ; do コマンド ; done
" は"条件
"
が真でない場合 "コマンド
" を繰り返します。
"break
" によってループから脱出できます。
"continue
" によってループ初めに戻り次の反復実行を再開します。
![]() |
ヒント |
---|---|
C 言語のような数字の繰り返しは " |
![]() |
ヒント |
---|---|
「ファイルに関してループしながらコマンドを反復実行」を参照下さい。 |
Debian システム上でできるだけポータブルなシェルプログラムとするには、ユーティリティープログラムを essential パッケージで提供されるプログラムだけに制約するのが賢明です。
"aptitude search ~E
" はessential (必須) パッケージをリストします。
"dpkg -L パッケージ名 |grep '/man/man.*/'
"
は パッケージ名
パッケージによって提供されるコマンドのマンページをリストします。
表12.7 シェルスクリプト用の小さなユーティリティープログラムを含むパッケージのリスト
パッケージ | ポプコン | サイズ | 説明 |
---|---|---|---|
dash
|
V:884, I:997 | 191 | sh 用の小型で高速の POSIX 準拠シェル |
coreutils
|
V:880, I:999 | 18307 | GNU コアユーティリティー |
grep
|
V:782, I:999 | 1266 | GNU grep , egrep and
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 ユーティリティー |
![]() |
ヒント |
---|---|
|
例は「Unix 的テキスト処理」を参照下さい。
表12.8 インタープリター関連のパッケージのリスト
パッケージ | ポプコン | サイズ | 文書 |
---|---|---|---|
dash
|
V:884, I:997 | 191 | sh: sh 用の小型高速 POSIX 準拠シェル |
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-doc and
perl-doc-html が提供する perl (1) と 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: python-doc が提供する
python3 (1) と html ページ |
tcl
|
V:25, I:218 | 21 | Tcl: tcl-doc が提供する
tcl (3) と詳細なマンページ |
tk
|
V:20, I:211 | 21 | Tk: tk-doc が提供する
tk (3) と詳細なマンページ |
ruby
|
V:86, I:208 | 29 | Ruby: ruby (1),
erb (1), irb (1),
rdoc (1), ri (1) |
Debian 上のタスクを自動化したい場合には、まず最初にインタープリター言語でタスクをスクリプト化すべきです。 インタープリター言語選択のガイドラインは:
もしタスクがシェルプログラムでできた CLI プログラムを組み合わせる簡単なタスクなら、dash
を使います。
もしタスクが簡単なタスクではなく何もないところから書くなら、python3
を使います。
もしタスクをするための加筆をする必要がある perl
, tcl
,
ruby
, ... で書かれたコードが Debian 上にすでに存在する場合には、その言語を使います。
もし出来上がったコードがおそすぎる場合には、実行速度にクリチカルな部分のみコンパイラー言語で書き直しインタープリター言語から呼びます。
ほとんどのインタープリターは基本的文法チェックやコード追跡の機能を提供します。
“dash -n script.sh” - シェルスクリプトの文法チェック
“dash -x script.sh” - シェルスクリプトのトレース
“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
のコードチェックの際には、 bash
のようなインタラクティブ環境を用意する「Readline のラッパー」を試します。
perl
のコードチェックの際には、Pythonのような REPL
(=READ + EVAL + PRINT + LOOP) 環境を提供するPerl 用の環境を試しましょう。
シェルスクリプトは魅力的な GUI プログラムを作るまで改善できます。echo
や
read
コマンドを使う鈍いやりとりに代えて、いわゆるダイアログプログラムを使うのがこのトリックです。
表12.9 ダイアログプログラムのリスト
パッケージ | ポプコン | サイズ | 説明 |
---|---|---|---|
x11-utils
|
V:192, I:566 | 651 | xmessage (1): window 中にメッセージや質問を表示 (X) |
whiptail
|
V:284, I:996 | 56 | シェルスクリプトからユーザーフレンリーなダイアログボックスを表示 (newt) |
dialog
|
V:11, I:99 | 1227 | シェルスクリプトからユーザーフレンリーなダイアログボックスを表示 (ncurses) |
zenity
|
V:76, I:363 | 183 | シェルスクリプトからグラフィカルなダイアログボックスを表示 (GTK) |
ssft
|
V:0, I:0 | 75 | シェルスクリプトフロントエンドツール (gettext を使った zenity や kdialog や dialog のラッパー) |
gettext
|
V:56, I:259 | 5818 | "/usr/bin/gettext.sh ": メッセージ翻訳 |
簡単なシェルスクリプトだけでできるほど GUI プログラムがいかに簡単ということを示す GUI プログラムの例は以下です。
このスクリプトはファイルの選択(デフォルトは/etc/motd
) に
zenity
を使い、それを表示します。
このスクリプトの GUI ローンチャーは以下のようにして生成できます 「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
シェル スクリプトでの GUI プログラムへのこのようなアプローチは簡単な選択ケースでのみ有効です。何らかの複雑のあるプログラムを書く場合には、もっと能力あるプラットフォームで書くことを考えましょう。
GUI ファイラー プログラムは、追加の拡張パッケージを使って選択されたファイルに対していくつかの人気ある動作を実行するように拡張できます。また、GUI ファイラー プログラムはあなたの特定のスクリプトを追加することで非常に特定のカスタム動作を実行するようにもできます。
KDE の場合、Creating Dolphin Service Menusを参照下さい。
Xfce の場合、Thunar - Custom Actions and 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++ ライブラリー v3 (開発用ファイル集) |
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 互換の 高速字句解析ジェネレータ |
bison
|
V:7, I:80 | 3116 | YACC互換のパーサジェネレータ |
susv2
|
I:0 | 16 | "The Single UNIX Specifications v2" を取得 |
susv3
|
I:0 | 16 | "The Single UNIX Specifications v3" を取得 |
susv4
|
I:0 | 16 | "The Single UNIX Specifications v4" を取得 |
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 | Free Pascal |
ここで、「Flex — 改良版 Lex」と「Bison — 改良版 Yacc」は、コンパイラーのようなプログラムがどのように高レベル記述を C 言語にすることで C 言語で書かれているかを示すために含めています。
C プログラム言語で書かれたプログラムをコンパイルする適正な環境を以下のようにして設定できます。
# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential
GNU C ライブラリーパッケージである libc6-dev
パッケージは、C
プログラム言語で使われるヘッダーファイルやライブラリールーチンの集合である C
標準ライブラリーを提供します。
C のリファレンスは以下を参照下さい。
"info libc
" (C ライブラリー関数リファレンス)
gcc
(1) と "info gcc
"
各 C ライブラリー関数名
(3)
Kernighan & Ritchie 著, "The C Programming Language", 第2版 (Prentice Hall)
Yacc 互換の前方参照可能な LR パーサーとか LALR パーサー生成ソフトは、いくつかのパッケージによって Debian 上で提供されています。
bison
(1) の入門書は "info bison
" の中にあります。
あなた自身の "main()
" と "yyerror()
"
を供給する必要があります。"main()
" は、Flex によって通常作成された
"yylex()
" を呼び出す "yyparse()
" を呼び出します。
シンプルなターミナル上の計算機プログラムの作成例をここに示します。
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 */ } %%
そして、これを試すためにシェルプロンプトから以下を実行しましょう:
$ 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
静的解析(lint) のようなツールは、自動静的コード分析に役立ちます。
Indent のようなツールは整合性をもってソースコードの再フォーマットすることで人間によるコードレビューを助けます。
Ctags のようなツールは、ソースコード中に見つかる名前のインデックス(とかタグ)を生成することで、人間がコードのレビューするのを助けます。
![]() |
ヒント |
---|---|
あなたの好きなエディター ( |
表12.12 静的コード分析ツールのリスト
パッケージ | ポプコン | サイズ | 説明 |
---|---|---|---|
vim-ale
|
I:0 | 2591 | Vim 8 や NeoVim 用の非同期静的解析エンジン |
vim-syntastic
|
I:3 | 1379 | Vim 用のシンタックスシェックのハック |
elpa-flycheck
|
V:0, I:1 | 808 | Emacs 用の現代的な同時進行のシンタックスチェック |
elpa-relint
|
V:0, I:0 | 147 | Emacs Lisp の正規表現 (regexp) の間違い検出器 |
cppcheck-gui
|
V:0, I:1 | 7224 | 静的 C/C++ コード分析ツール (GUI) |
shellcheck
|
V:2, I:13 | 18987 | シェルスクリプトの静的解析(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++ の静的解析(lint)ツール |
splint
|
V:0, I:2 | 2320 | C プログラムを静的にバグのチェックするためのツール |
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
" を使ってデバッグ情報を付けてコンパイルされた
"program
" に使う簡単な例です。
$ 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
システム上ではストリップされているべきなので、ほとんどのデバグシンボルは普通のパッケージからは除かれています。gdb
(1)
を使って Debian パッケージをデバグするためには、*-dbgsym
パッケージ(例えばcoreutils
の場合は
coreutils-dbgsym
)をインストールする必要があります。ソースパッケージは、普通のバイナリーパッケージとともに
*-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 ./
必要に応じてバグを修正します。
例えば以下のように、既存パッケージを再コンパイルする時は "+debug1
"
を後ろに付けたり、リリース前のパッケージをコンパイルする時は "~pre1
" を後ろに付けたりと、正規の
Debian バージョンとかち合わないようにパッケージバージョンを増やします。
$ dch -i
以下のようにしてデバグシンボル付きでパッケージをコンパイルしてインストールします。
$ export DEB_BUILD_OPTIONS="nostrip noopt" $ debuild $ cd .. $ sudo debi package_name*.changes
パッケージのビルドスクリプトを確認して、バイナリーのコンパイルに確実に "CFLAGS=-g -Wall
"
が使われているようにします。
プログラムがクラッシュするのに出会った場合に、バックトレース情報をバグレポートに切り貼りして報告するのは良い考えです。
バックトレースはgdb
(1) によって以下のような段取りで得られます。
GDBの中でクラッシュ アプローチ:
GDB からプログラムを実行します。
プログラムがクラッシュします。
GDB プロンプトで "bt
" と打ちます。
先にクラッシュ アプローチ:
“/etc/security/limits.conf” ファイルを更新して以下を含めます:
* soft core unlimited
シェルプロンプトで "ulimit -c unlimited
" と打ちます。
このシェルプロンプトからプログラムを実行します。
プログラムがクラッシュしてコアダンプファイルができます。
"gdb gdb ./program_binary core
" として core dump ファイルを GDB にロードします。
GDB プロンプトで "bt
" と打ちます。
無限ループやキーボードが凍結した場合、Ctrl-\
か Ctrl-C
を押すか “kill -ABRT PID
”
を実行することでプログラムを強制終了できます。(「プロセスの停止」を参照下さい)
![]() |
ヒント |
---|---|
しばしば、一番上数行が " $ 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)
`chroot` された環境下で ls
(1) が機能するには、上記ライブラリーがあなたの `chroot`
された環境内で利用可能である必要があります。
「プログラム活動の追跡」を参照下さい。
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 (3) デバッガ |
libdmalloc5
|
V:0, I:2 | 390 | メモリーアロケーションのデバグ用ライブラリー |
duma
|
V:0, I:0 | 296 | C および C++ プログラムのバッファオーバーランとアンダーランを検出するライブラリー |
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 | クロスプラットフォームでオープンソースの make システム cmake (1) |
ninja-build
|
V:6, I:41 | 428 | Make と似た精神の小さなビルドシステム ninja (1) |
meson
|
V:3, I:22 | 3759 | ninja の上に構築された高生産性のビルドシステム meson (1) |
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 コードです。各行は make
による変数置換後シェルによって解釈されます。スクリプトを継続する行末には "\
"
を使います。シェルスクリプトの環境変数のための "$
" を入力するためには
"$$
" を使います。
ターゲットや前提に関するインプリシット (暗黙) ルールは、例えば以下のように書けます。
%.o: %.c header.h
上記で、ターゲットは "%
" という文字を (1つだけ)
含んでいます。"%
"
は実際のターゲットファイル名の空でないいかなる部分文字列ともマッチします。前提もまた同様にそれらの名前が実際のターゲットファイル名にどう関連するかを示すために
"%
" を用いることができます。
"make -p -f/dev/null
" を実行して自動的な内部ルールを確認下さい。
Autotools は多くの Unix-like システムに移植可能なソースコードパッケージを作ることを援助するように設計された一連のプログラムツールです。
オリジナルのソースを保有し、それが
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 パッケージを作成できます。
ソフトウェアービルドシステムは進化してきています:
Make の上に構築された Autotools は 1990 年代より移植可能なビルドインフラのデファクトスタンダードです。これは非常に遅いです。
2000 年に最初にリリースされた CMake は、スピードが大幅向上させたが、依然として本質的に遅い Make の上に構築されていました。(現在は、Ninja がバックエンドで使えます。)
2012 年に最初にリリースされた Ninja は、さらなるビルド速度の向上のために Make の置き換えを意図し、その入力ファイルはハイレベルビルドシステムが生成するように設計されています。
2013 年に最初にリリースされた Meson は、新しく人気ある Ninja をバックエンドに使うハイレベルビルドシステムです。
"The Meson Build system" や "The Ninja build system" にある文書を参照下さい。
基本的な対話式動的ウェッブページは以下のようにして作られます。
質問 (クエリー) はブラウザーのユーザーに HTML フォームを使って提示されます。
フォームのエントリーを埋めたりクリックすることによって以下の符号化されたパラメーター付きの 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"
".
ウェッブサーバー上の CGI プログラム
("program.*
" のいずれでも) が環境変数
"$QUERY_STRING
" の下で実行されます。
CGI プログラムの STDOUT
(標準出力)
がウエブブラウザーに送られ対話式の動的なウェッブページとして表示されます。
セキュリティー上、CGI パラメーターを解釈する手作りの急ごしらえのプログラムは作らない方が賢明です。Perl や Python にはこのための確立したモジュールが存在します。PHP はこの様な機能が同梱されています。クライアントでのデーターのストレージの必要がある場合、HTTP クッキーが使われます。クライアントサイドのデーター処理が必要な場合、Javascript が良く使われます。
詳しくは、Common Gateway Interface や The Apache Software Foundation や JavaScript を参照下さい。
https://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial を URL として直接ブラウザーのアドレスに入れ Google で"CGI tutorial" を検索するとグーグルサーバー上の CGI スクリプトが動いているのを観察する良い例です。
Debian パッケージを作りたい場合には、次を読みましょう。
基本的なポーティングプロセスの理解のために、「安定版システムへのパッケージ移植」
基本的な chroot 技術の理解のために、「Chroot システム」
debuild
(1) と sbuild
(1)
リコンパイルとデバグは「Debian パッケージのデバグ」
Guide for Debian
Maintainers (debmake-doc
パッケージ)
Debian Developer's
Reference (developers-reference
パッケージ)
Debian ポリシーマニュアル
(debian-policy
パッケージ)
debmake
や dh-make
や
dh-make-perl
等のパッケージングを補助するパッケージがあります。