入門 bash 読書ノート 3/3¶
- 著者:
Cameron Newham, Bill Rosenblatt
- 訳者:
株式会社クイープ
- 出版社:
オライリー・ジャパン
- 発行年:
2005 年
- ISBN:
978-4-87311-254-1
8 章 プロセスの操作¶
Cygwin ユーザーが読んでも役に立つと信じて本章を読む。
<UNIX は、ユーザーごとに複数のプロセスの制御を可能にした最初の小型コンピュータオペレーティングシステムとしてもよく知られている> (p. 209)
<プロセスを識別し、ログインセッションやシェルスクリプトでそれらを制御するための最も基本的な要素から見ていく> (p. 209)
<プロセスどうしを通信させる仕組みについて調べる> (p. 209)
8.1 プロセス ID とジョブ番号¶
<プロセスが生成されると、必ず プロセス ID という番号が振られる> (p. 210) コマンドを
&
付きで実行すると、コンソールに[1] 4000
のような表示が出る。最初の括弧つきの番号が ジョブ番号 を示す。<ジョブという言葉は、基本的に、シェルから呼び出されたコマンドラインを指す> (p. 210)
8.2 ジョブ制御¶
<ただし、ジョブ番号のほうは重要だ。 ジョブ制御 を行うシェルコマンドで使用するからである> (p. 211)
<ジョブをバックグラウンドで起動した後は、そのまま完了させるか、フォアグラウ ンド へ移すか、または シグナル というメッセージを送りつけることができる> (p. 211)
8.2.1 フォアグラウントとバックグラウンド¶
jobs コマンドでジョブの一覧表示。オプションが色々ある。
引数なしで fg と入力すると、バックグランドで最後に実行されたジョブがフォアグラウンドに移る。
8.2.2 ジョブの一時停止¶
<一時停止するには、ジョブの実行中に Ctrl + Z キーを押す> (p. 213) ここで Ctrl + Z は
susp
に設定されていることを仮定している。<停止したジョブを再開し、フォアグラウンドで続行したい場合には、ここで fg と入力すればよい> (p. 213)
<(いつものように)コマンドをフォアグラウンドに実行したところ、思ったよりも処理に時間がかかっていることに気付く。コマンドはきちんと終了させたいが、端末の制御を取り戻して他の作業も行いたい。このような場合には、Ctrl + Z キーを押してから bg と入力すれば、ジョブをバックグラウンドに移すことができる> (p. 214) 脚注のネットワーク経由での実行に関する注意も読む。
8.3 シグナル¶
Ctrl + Z と Ctrl + C は、<どちらもプロセスに シグナル を送信するという特殊な行動をとる> (p. 214)
シグナルとは、あるプロセスから別のプロセスに送信されるメッセージととらえればよいようだ。
シグナルを使用するスクリプトを書くときは、可搬性を高めるために番号ではなく名前を使用する。kill -l で一覧できる。
8.3.1 コントロールキーのシグナル¶
<説明しておいて何だが、この方法はお勧めできないことを付け加えておかなければならない> (p. 216)
8.3.2 kill¶
デフォルトでは kill は TERM シグナルを送信する。ただ、効果としては INT シグナルと同じとのこと。
<すべてを説明すると込み入った話になるので、次の説明で勘弁して欲しい> (p. 216)
kill %1 は「ジョブ番号 1 のプロセスを(TERM シグナルで)停止する」。
kill -QUIT %1 は「ジョブ番号 1 のプロセスを(QUIT シグナルで)終了する」。
kill -KILL %1 は「ジョブ番号 1 のプロセスを(KILL シグナルで)終了する」。
<TERM シグナルと QUIT シグナルは、プロセスを終了する前に「後始末」をする機会を設けるが、KILL シグナルは、たとえ計算中であったとしても、プロセスを強制終了する。 KILL シグナルは最後の手段として使用すること。> (pp. 217-218)
8.3.3 ps¶
<プロセス ID は ps コマンドで取得することができる> (p. 218)
<ps にはオプションが複数あるが、UNIX のバージョンによって異なる> (p. 218) Cygwin 環境では ps -ax が怒られるから、BSD ではなく System V 系統なのだろうか。
8.4 トラップ¶
8.4.2 プロセス ID と一時ファイル¶
<
$$
は、現在のシェルのプロセス ID を保持する特別なシェル変数である> (p. 224)<
$!
には、最後に実行したバックグラウンドジョブのプロセス ID が含まれている > (p. 224)<trap コマンドに指定されたコマンド文字列が、実行されるまで 評価さ れない ことに注意しよう。したがって、コマンド文字列の
$msgfile
には、必ず正しい値が含まれる。コマンド文字列を単一引用符で囲んだのは、そのためである> (p. 225)
8.4.5 トラップのリセット¶
trap コマンドに引数としてハイフンだけを指定すると、シグナル受信時の動作がデフォルト(プロセスの中止)に戻る。
8.5 コルーチン¶
<2 つ(以上)のプロセスが同時に実行されるようにプログラムされていて、プロセスどうしが互いにやり取りすることが可能である場合、それらを コルーチン (coroutine) という> (p. 227)
<パイプラインはコルーチンの一例だ> (p. 227)
8.5.1 wait¶
<引数を指定しないと、wait はバックグラウンドジョブがすべて終了するまで待機する> (p. 228)
8.5.2 コルーチンの利点と欠点¶
以下の用語がだいたい人に説明できる程度まで、複数プロセス同時実行のメリットに関する理解を深めたい。
CPU 集約型
入出力集約型
対話型
スラッシンング
8.5.3 並列化¶
<プロセスをコルーチンに分割することを、ジョブを 並列化 するとも言う> (p. 229)
<この場合、コルーチンの実行時間は、すべてのプロセスの実行時間を合計したものではなく、基本的には、実行時間が最も長いものに若干のオーバーヘッドを足したものとなる(ただし、すべての CPU が 1 つのディスクドライブを共有していた場合、I/O 関連のスラッシングの可能性はまだ消えない)> (p. 230)
<せっかく並列化を施して処理時間を短縮したのに、追加したコードの実行時間で相殺されてしまったのでは意味がない> (p. 231)
<複雑な並列プログラムになると、本体の目的を達成するコードよりも、特殊な状況に対応するコードのほうが圧倒的に多いほどである> (p. 231)
8.6 サブシェル¶
8.6.2 入れ子のサブシェル¶
<シェルコードの一部を(中かっこではなく)かっこで囲むと、そのコードはサブシェルで実行される。これを 入れ子 の(またはネストした)サブシェルと言う> (p. 232)
通常は、コマンドブロック(中括弧)の場合よりも効率が悪い。
サブシェルとコマンドブロックの違いは、そのほとんどが「スコープ」に関係するもの。シェル変数やシグナルトラップの有効範囲が違う。
<コードの入れ子をサポートしている言語では、入れ子のコード内で定義されるものには、そこだけに限定されたスコープが割り当てられることが望ましい、とされている。このため、変数やシグナルトラップのスコープに関しては、入れ子のサブシェルのほうがコマンドブロックよりも厳密な制御が可能である。したがって、変数の定義やシグナルトラップが必要で、効率を度外視できるのであれば、コマンドブロックよりもサブシェルを使用したほうがよいだろう> (p. 233)
8.7 プロセス置換¶
cmp <(program1) <(program2)
program1 と program2 を同時に実行して、
それらの出力を 名前付きパイプ につなぎ、
cmp がそれぞれのパイプからデータを読み取り、比較する。
9 章 シェルプログラミングのデバッグ¶
9.1 基本的なデバッグ補助¶
9.1.1 set のオプション¶
組み込み変数
PS4
は set -o xtrace の出力行の先頭の文字列。展開レベル次第で、出力行の先頭の文字列の先頭にPS4
の 1 文字目が付加される。
9.2 bash デバッガ¶
<プログラムにおいて実行を停止する場所を指定する。これを ブレークポイント という> (p. 245)
<プログラムにおいて指定された数の文を実行する。これを ステップ実行 という> (p. 245)
<exec に引数としてコマンドラインを渡すと、それらは現在のプログラム(同じプロセス)で実行される。したがって、exec を実行するとシェルが 直ちに停止し、 exec の引数と置換される> (p. 247)
exec が危険な存在であることを指摘している。
10 章 bash の管理¶
10.1 標準シェルとしての bash のインストール¶
<1 行目では、
$PATH
環境変数をfor
ループの項目リストとして使用できるようにしている> (p. 268)IFS=: for d in $PATH; do # 何か処理
10.1.1 POSIX モード¶
POSIX は Portable Operating System Interface の略らしい。X はどこから?
<bash はデフォルトのモードでも POSIX にほぼ 100% 準拠している。 POSIX へのこだわりがあるならば、bash を POSIX モードで実行することができる。そのためには、
--posix
オプションを指定するか、シェルで set -o posix を設定する> (p. 269)
10.1.2 コマンドラインオプション¶
表 10-1 より、使えそうなものをノート:
-c string
string
からコマンドを読み取る。-i
対話型シェル。-l, --login
ログインシェル。--help
使用法を示すメッセージを表示する。--noprofile
/etc/profile
やユーザーの初期設定ファイルをロードしない。--norc
対話型シェルの場合、~/.bashrc
をロードしない。--rcfile file
対話型シェルの場合、~/.bashrc
の代わりにfile
をロードする。--init-file file
同上。<コマンドラインで複数文字のオプションを指定する場合には、1 文字のオプションよりも前に指定しなければならない> (p. 270)
10.2 環境のカスタマイズ¶
bash は
/etc/profile
を読み込んでから~/.bash_profile
を読み込む。umask や ulimit コマンドを使用するのは前者。
10.2.1 umask¶
<ここでは 8 進表記を使用して umask の説明をする。おそらく知っていると思うが、パーミッションの数字は、(左から右に)所有者、所有者が属するグループ、その他のユーザーへのパーミッションを表す。数字はそれぞれ 3 ビットで構成され、左から右に、読み取り、書き込み、実行のパーミッションを指定する。 (ファイルがディレクトリの場合、「実行」パーミッションは「検索」パーミッションとなる。検索パーミッションとは、ディレクトリを移動したりファイルの一覧を取得したりするためのパーミッションである> (p. 271)
10.2.2 ulimit¶
ulimit コマンドで、ユーザーが利用できるシステムリソースに制限を設けることができる。
11 章 シェルスクリプティング¶
本章では、<保守可能なシェルスクリプトを作成する方法を紹介> (p. 279) するようだ。
11.1 スクリプトは何をするのか¶
11.1.2 変数と定数¶
<ヘッダーとコメントは、コードを文書化するための方法の 1 つにすぎない> (p. 281)
<よい名前とは、短くてわかりやすいものである。(略)長い名前にしてはならない。(略)わかりやすい名前のメリットを帳消しにするほど、スクリプトを煩雑にするだけである> (p. 281)
11.2 スクリプトの起動¶
<プログラマはユーザーの操作ができるだけ楽になるように努力しなければならない> (p. 281)
<Free Software Foundation では、GNU ソフトウェアを作成するためのガイドラインを公開し、 UNIX ユーティリティの標準的な使用法を提案している> (p. 282) URL が脚注にある。
<注意しなければならない点が 1 つある。それは、ユーザーの環境において特定の環境変数が設定されていることを前提とする場合である。環境変数が設定されていることをあてにするくらいなら、スクリプトの設計を見直して、その値を引数として指定できるようにしたほうがよいだろう> (p. 283)
11.3 その他の問題点¶
bash スクリプトに関するものだけノート。
必ず
#!/bin/bash
とすること。ホワイトスペースに注意する。等号の前後、開き括弧の後ろ、閉じ括弧の前が危ない。
評価演算子
[...]
の使用に注意。=
なのか-eq
なのか等。
11.4 bash を使用しない¶
大量の処理をすばやく実行する場合や、数学的な計算を要する場合は C/C++ の使用を検討したり、システム間の可搬性を重視する場合は、 Python や Perl のほうが適しているといった判断をすること。適材適所。
12 章 bash の導入¶
Cygwin ユーザーである記者は特に読まなくてよい?
付録 A 関連シェル¶
A.3 Korn シェル¶
<唯一の欠点は、数年おきにしかアップグレードされないことだ> (p. 302)とある。今でもそうなのだろうか。
A.5 zsh¶
<特に「パワーユーザー」にお勧めである> (p. 303)
付録 B リファレンス¶
B.8 入出力リダイレクト¶
出力・エラーリダイレクトには
&>file
と>&file
の 2 つの形式がある。後者のほうが望ましい。
付録 D プログラム可能な補完¶
<補完メカニズムにフックを仕掛けて、2 章で説明した組み込みのテキスト補完機能を拡張するものである> (p. 333)
Tab キーが押されたときのシェルの対応を complete コマンドで指定する。
# -A file が「補完するのはファイルリストだ」ということを指示する # # -X '!*.@(Z|gz|tgz)' がファイル名パターンのフィルターを指示する complete -A file -X '!*.@(Z|gz|tgz)' gunzip
compgen は補完文字列を確認するのに利用できる。
complete -A file -X '!*.@(Z|gz|tgz)'