LFCS — Linux Foundation認定システム管理者
シェルはいつ何を代わりにやってくれるのか
一言でいうと
試験でコマンドが期待と違って動く理由の大半は、コマンドではなくシェルがコマンドを実行する前にしたことです。展開のタイミング、ファイルディスクリプター、findの式の文法。この3つが、必須コマンド領域の骨格です。
なぜ必要なのか
rm -f /var/log/*.gzを実行したのに、ファイルが消えません。rmを疑いますが、犯人はrmではありません。ワイルドカードを実際のファイル一覧に置き換えるのはシェルであり、シェルはコマンドを呼び出す前にその仕事を終えます。一致するファイルがなければ、シェルは*.gzという文字そのままを引数として渡してしまい、rmは、そのような名前のファイルはないと答えます。
引用符の意味も、ここで分かれます。二重引用符は変数展開は生かして、単語分割とファイル名展開だけを防ぎます。単一引用符はすべてを防ぎます。空白を含むパスを扱うときに二重引用符を書き漏らすと、引数1つが2つに分かれてしまいます。試験でパスに空白が入った問題が出る理由が、これです。
どう動くのか
リダイレクトはファイルディスクリプターの操作です。すべてのプロセスは、0(標準入力)、1(標準出力)、2(標準エラー出力)を持って始まります。> out.txtは「ディスクリプター1が指す先を、このファイルに変える」という意味で、2>&1は「ディスクリプター2を、今ディスクリプター1が指している先と同じ場所に複製する」という意味です。
順序が重要な理由が、まさにこの「今」です。
| 表記 | 結果 |
|---|---|
cmd > f 2>&1 |
1をfに変えたあと、2をfに複製 → 両方ともファイル |
cmd 2>&1 > f |
2をターミナルに複製したあと、1だけをfに変更 → エラーは画面 |
findはコマンドではなく式の言語です。-name、-size、-mtime、-permはオプションではなく、真偽を返す述語で、並べると暗黙のANDでつながります。-printや-execも述語で、副作用のある述語にすぎません。そのため、-oでORを使うときに括弧を書き漏らすと、優先順位がずれて、見当違いのファイルが選ばれます。
数値の引数には符号の規則があります。-mtime 30は「ちょうど30日前の区間」、-mtime +30は「30日よりも古い」、-mtime -30は「30日以内」です。-perm 644は完全一致、-perm -644はそのビットをすべて含む、-perm /644は、そのうちのどれか1つでも含む、です。試験で最も減点される箇所です。
現場での姿
筆者がまとめたファイルディスクリプターの記事には、こんな事例が出てきます。ログファイルを誤って削除したのに、そのファイルを開いていたプロセスがまだ生きていました。ディレクトリエントリは消えましたが、リンク数が0になっても、開かれたディスクリプターが残っていれば、カーネルはブロックを回収しません。そのため、/proc/<PID>/fd/<번호>をそのままコピーするだけで、内容を復活させられました。逆に、同じ性質を利用して、truncate -s 0 /proc/<PID>/fd/<번호>で、プロセスを生かしたまま領域だけを空にすることもできますが、番号を間違えると、無事なファイルが消えます(プレースホルダーはいずれも番号です)。
パイプラインでは、yes | head -1が教科書的な例です。headが先に終わると、yesは、読む側のいないパイプに書き込もうとしてSIGPIPEで死にます。これが正常な動作です。そして、筆者のシェルに関する記事が繰り返し強調する原則の1つ。lsの出力をパースせず、グロブで順に処理します。ファイル名に空白や改行が入った瞬間、lsのパースは静かに間違います。
試験会場で手が固まらないために
LFCSは、2時間で課題を手で解く試験なので、知っていることと制限時間内に打てることは違います。いくつかのことを身につけておくだけで、時間が大きく減ります。
ドキュメントをどこで見るかを決めておきます。インターネットはありませんが、manと--helpはあります。manの中で/で検索し、nで次に進むことを覚えておくだけで、オプション1つを探すのに数秒で済みます。そして、man -kで単語からコマンドを逆引きできることを知らないと、名前を思い出せないコマンド1つに、数分を使ってしまいます。
元に戻せないものを先に確認します。rm・mkfs・dd・>は確認しません。特にリダイレクトは、コマンドを打った瞬間に、対象のファイルを先に空にします。そのため、元のファイルを読んで、同じファイルに書く形は、いつも内容を消します。中間ファイルを経由するか、その場編集のオプションを使います。
変更する前にコピーを取ります。設定ファイルを変更するとき、日付を付けて1つコピーしておくのに2秒かかり、それがないと、元に戻すのに数分かかります。試験でも実務でも同じです。
確認までが1つの課題です。サービスを起動する課題は、今動いていることと、再起動後にも起動することが別の設定で、両方が問われます。ユーザーを作成する課題は、シェルとホームディレクトリとグループまでが、普通は含まれます。答えを出したと思った時点で、もう一度確認する30秒は、すべて解き終わってから間違いを探すよりも、ずっと安くつきます。
最後に、詰まったら飛ばします。部分点制なので、1つの課題にこだわっている間に、解けたはずの2つの課題が過ぎ去ります。飛ばすときは、何を残してきたかを書き留めておき、時間が余ったら戻ってきます。
次のラボですること
/root/lfcs-ess/にディレクトリツリーを作り、ハードリンクとシンボリックリンクのinodeの違いを自分で確認します。findをサイズ・時刻・権限の条件で組み合わせて一覧を取り出し、同じディレクトリをgzipとxzでそれぞれ圧縮して、サイズを比較します。最後に、diff -uでパッチを作り、コピーに適用します。その次のラボでは、自分で作ったログをgrep・sed・awk・jq・yqで加工します。