コマンドシーケンスとパイプライン

LinuxBeginner
オンラインで実践に進む

はじめに

小さな Linux コマンドも、shell がコマンド同士を連携させると、はるかに便利になります。コマンドは終了ステータスによって成功または失敗を報告します。シーケンス演算子は次に実行するコマンドを決定し、パイプは一方のコマンドの標準出力を別のコマンドの標準入力へ接続します。

この実験では、これらの概念を一つずつ学びます。その後、grepcutwcsortuniq を使って、小さなサービスイベントデータセットを変換します。後続のテキスト処理の実験では、これらのフィルターをさらに詳しく扱います。ここでは、コマンド間でデータと判断がどのように受け渡されるかに焦点を当てます。

コマンドの終了ステータスを確認する

このステップでは、画面に表示されるコマンドの動作と、shell が記録する数値ステータスを関連付けます。

終了ステータスが 0 なら成功を表し、0 以外の値なら、コマンドが要求された操作を完了できなかったことを表します。まず、存在するファイルのテストを成功させ、直後に最新のステータスを保持する $? を表示します。

cd /home/labex/project/pipeline-lab
test -f events.csv
echo $?

出力は 0 になります。次に、存在しないファイルをテストします。

test -f missing.csv
echo $?

ステータスは 0 以外になります。後続のコマンドを実行すると $? の値は置き換えられるため、必ず直後に読み取ってください。

if 文を使って、確認結果を安定した形で保存します。shell スクリプトの詳しい内容は後で学びます。ここでは、ステータスをテキストに変換するためだけに使用します。

if test -f events.csv; then echo "events.csv is ready"; else echo "events.csv is missing"; fi > status-result.txt
cat status-result.txt

次に実行するコマンドを制御する

このステップでは、無条件のコマンド演算子と条件付きコマンド演算子を比較します。

セミコロンは、直前のコマンドの結果に関係なく、次のコマンドを実行します。

false; echo "semicolon continues"

&& は、左側のコマンドが成功した場合にだけ右側のコマンドを実行します。

test -f events.csv && echo "input found"
test -f missing.csv && echo "you should not see this"

|| は、左側のコマンドが失敗した場合にだけ右側のコマンドを実行します。

test -f missing.csv || echo "input missing"

これらの演算子を使うと、成功または失敗に応じた簡単な判断を表現できます。データセットが存在する場合だけコピーし、存在しない場合はエラーを表示します。

test -f events.csv && cp events.csv working.csv || echo "Copy failed"

条件付きで作成したコピーが、元のファイルと一致することを確認します。

cmp events.csv working.csv && echo "guarded copy matches" > sequence-result.txt
cat sequence-result.txt

複雑なロジックでは、読みやすい if 文を使用してください。長い &&|| の連鎖は、意味が分かりにくくなることがあります。

パイプラインで出力を渡す

このステップでは、| でコマンドを接続し、各段階でデータの流れがどのように絞り込まれるかを確認します。

左側のコマンドは標準出力をパイプへ書き込み、右側のコマンドはそのデータを標準入力として読み取ります。ERROR レコードだけを抽出します。

cd /home/labex/project/pipeline-lab
cat events.csv | grep ',ERROR,'

grep はファイルを直接読み取れるため、次の短い形式でも同じ結果になります。

grep ',ERROR,' events.csv

wc -l を追加して、一致した行数を数えます。

grep ',ERROR,' events.csv | wc -l

フィルター済みのデータと件数を保存します。tee は標準入力を複製します。一方のコピーを error-events.csv に書き込み、もう一方を標準出力から次のコマンドへ渡します。そのため、最後の wc -l は保存された行とまったく同じ行数を数えます。

grep ',ERROR,' events.csv | tee error-events.csv | wc -l > error-count.txt
cat error-events.csv
cat error-count.txt

パイプラインの実行後、2 つのファイルを確認します。error-events.csv には一致したレコードが含まれ、error-count.txt にはその件数が含まれます。

cut でフィールドを抽出する

このステップでは、各 CSV 行を区切り文字で分けられたフィールドとして扱います。

cut -d, -f1 はカンマを区切り文字として使用し、フィールド 1 であるサービス名を表示します。

cd /home/labex/project/pipeline-lab
cut -d, -f1 events.csv

サービス名と severity フィールドをまとめて表示します。

cut -d, -f1,2 events.csv

フィルターと抽出を組み合わせて、警告を出したサービスだけを一覧表示します。

grep ',WARN,' events.csv | cut -d, -f1

この中間結果を保存します。

grep ',WARN,' events.csv | cut -d, -f1 > warning-services.txt
cat warning-services.txt

cut は、フィールド内に区切り文字が含まれない単純なレコードに適しています。より複雑な形式では、awk や形式に対応したツールが必要になる場合があります。

繰り返し値を並べ替えて数える

このステップでは、完全な頻度集計パイプラインを作成し、uniq の前に並べ替えが必要な理由を理解します。

uniq は、隣接している同じ行だけをまとめます。まずサービス名を抽出し、同じ値が隣り合うように並べ替えます。

cd /home/labex/project/pipeline-lab
cut -d, -f1 events.csv | sort

uniq -c を追加して、同じ名前が連続しているまとまりごとの件数を数えます。

cut -d, -f1 events.csv | sort | uniq -c

件数を数値として降順に並べ替えます。sort -k1,1nr は、1 番目のフィールドを数値として扱い、逆順に並べるキーとして使用します。

cut -d, -f1 events.csv | sort | uniq -c | sort -k1,1nr

最終レポートを保存します。

cut -d, -f1 events.csv | sort | uniq -c | sort -k1,1nr > service-frequency.txt
cat service-frequency.txt

このパイプラインは左から右へ読みます。抽出 → 並べ替え → 隣接する重複のカウント → 件数による順位付け、という流れです。

まとめ

shell の成功シグナルとして終了ステータスを使用し、;&&|| でコマンドの実行を制御し、明確な段階を持つパイプラインを作成しました。さらに、レコードのフィルタリング、フィールドの抽出、行数のカウント、値の並べ替え、重複のカウントを行いました。これらは、次のデータパイプライン Challenge に必要な基本操作です。