順番に読み進めながら学べます

コマンド連携 — grep / awk の結果で分岐する

この記事は、基礎コマンドからシェルスクリプトまでLinuxの実践的なスキルを1からマスターする「Linux入門講座の一部」です。
スクリプト内でn=$(grep -c ERROR access.log)で件数を変数化し、total=$(awk '{s+=$1} END{print s}')で合計を取り、if [ "$n" -ge 2 ]で分岐するスキャナを、図解とブラウザ端末で作ります。

スクリプトの中でコマンドを呼ぶ — パイプとコマンド置換

シェルスクリプトの本当の力は、grep awk sed sort wcといった一般コマンドをスクリプト内で組み合わせられる点にあります

スクリプトの中でもパイプ|でコマンドをつなぎ、$(cmd)のコマンド置換でその出力を取り込めます。

n=$(grep -c error log.txt)と書くと、grep -cが出した一致行数を変数nに入れられます。

total=$(awk '{s+=$1} END{print s}' f)のように集計結果を変数にすることもできます。

コマンドの結果を変数にすると、その値を使ってスクリプトの動きを変えられます

printf 'INFO ok\nERROR disk\nINFO ok\nERROR cpu\n' > sys.log   # 素材を作成
vi count.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   n=$(grep -c ERROR sys.log)
#   echo "ERROR の件数: $n"
chmod +x count.sh
./count.sh                                                      # ERROR の件数: 2
件数を変数にして分岐する
n=$(grep -c ERROR access.log)n ≥ 2警告を出すn < 2正常を出す2 件以上1 件以下警告正常
grep -cで数えた件数を変数nにし、ifで 2 件以上なら警告、そうでなければ正常に分岐します。
書き方意味
n=$(grep -c pat f)一致した行数を変数 n に入れるn=$(grep -c error log.txt)
$(cmd | cmd)パイプの結果を変数に取り込むtop=$(sort log.txt | head -1)
if [ "$n" -ge 2 ]; then …件数が2件以上かで条件分岐するif [ "$n" -ge 2 ]; then echo warn; fi

アクセスログ風のデータをgrep -cで数え、エラーが2件以上なら警告、そうでなければ正常と表示するスキャナを作ります。

printf 'INFO login\nERROR timeout\nINFO logout\nERROR 500\nINFO ping\n' > access.logで素材ファイルを作成してください。

vi scan.shscan.shを開き、iで挿入モードに入って、n=$(grep -c ERROR access.log)で件数を変数にし、if [ "$n" -ge 2 ]; then … else … fiで「警告: エラー $n 件」か「正常」を出すスクリプトを書いてください(先頭に#!/bin/sh)。書けたらEsc:wqで保存します。

chmod +x scan.shで実行権限を付け、./scan.shを実行して警告が出ることを確認してください。

④ 書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。

(正しく実行できれば解説が表示されます)

Linux console
0 / 3 実行済み
Loading Linux Terminal...

集計して結果で動きを変える — awk と分岐

件数だけでなく、数値を合計して判定することもできます

total=$(awk '{s+=$1} END{print s}' f)は各行の1列目を足し合わせ、その合計を変数totalに入れます。

同じ語ごとの出現数を数えたいときはsort f | uniq -cで並べ替えてから数え、その結果を$(...)で取り込むこともできます。

得られた合計をif [ "$total" -gt 100 ]; then …のようにしきい値と比べれば、「合計が一定を超えたら警告」といった判定ができます。

集計と分岐を1つのスクリプトにまとめると、データを読んで状況を判断する実用的なツールになります

printf '40\n30\n50\n' > sales.txt   # 1 列の数値データ
vi sum.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   total=$(awk '{s+=$1} END{print s}' sales.txt)
#   if [ "$total" -gt 100 ]; then
#     echo "合計 $total: 目標達成"
#   else
#     echo "合計 $total: 未達"
#   fi
chmod +x sum.sh
./sum.sh                              # 合計 120: 目標達成
printf 'a\na\nb\n' > tags.txt   # 同じ語が並ぶ素材
sort tags.txt | uniq -c          # 並べ替えてから件数を数える
# 出力:
#   2 a
#   1 b
合計を集計して値で分岐する
total=$(awk … errors.txt)total > 20要対応total ≤ 20許容内超過以内しきい値超えしきい値以内
awkで合計したtotalifでしきい値 20 と比べ、超えたら要対応、以内なら許容内に分岐します。
書き方意味
awk '{s+=$1} END{print s}' f1列目を合計して集計awk '{s+=$1} END{print s}' nums.txt
sort f | uniq -c集計前に並べ替えて件数を数えるsort tags.txt | uniq -c
if [ "$total" -gt N ]; then …合計をしきい値 N と比べて分岐if [ "$total" -gt 100 ]; then …

数値データをawkで合計し、しきい値を超えたかどうかで結果を変えるスクリプトを作ります。

printf '12\n8\n5\n3\n' > errors.txtで1列の数値データを作成してください。

vi sum.shsum.shを開き、iで挿入モードに入って、total=$(awk '{s+=$1} END{print s}' errors.txt)で合計を変数にし、if [ "$total" -gt 20 ]; then … else … fiで「要対応: 合計 $total」か「許容内: 合計 $total」を出すスクリプトを書いてください(先頭に#!/bin/sh)。書けたらEsc:wqで保存します。

chmod +x sum.shで実行権限を付け、./sum.shを実行して合計で分岐した結果が出ることを確認してください。

④ 書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。

Linux console
0 / 3 実行済み
Loading Linux Terminal...

出力とエラーを振り分ける — > と 2>

スクリプトの結果を画面ではなくファイルに残したいことがあります。

./scan.sh > report.txtは通常の出力(標準出力)をreport.txtに書き込みます。

echo "..." 1>&2のようにエラーメッセージを標準エラーへ出しておけば、./scan.sh > report.txt 2> error.log正常な結果とエラーを別ファイルに分けられます

vi job.sh   # エディタで開き、次の内容を書いて :wq で保存
#   #!/bin/sh
#   echo "処理を開始しました"          # 標準出力
#   echo "注意: 入力が空でした" 1>&2     # 標準エラー
chmod +x job.sh
./job.sh > out.txt 2> err.txt        # 出力とエラーを別ファイルへ
cat out.txt                          # 処理を開始しました
cat err.txt                          # 注意: 入力が空でした
出力とエラーの振り分け
./scan.shecho の出力 (標準出力)> report.txt./scan.shecho … 1>&2 (標準エラー)2> error.log標準出力標準エラー
標準出力は> report.txt、標準エラーは2> error.logと別々に振り分けられます。
書き方意味
cmd > out標準出力をファイルに書き込む./scan.sh > report.txt
echo "…" 1>&2メッセージを標準エラーへ出すecho "failed" 1>&2
cmd > out 2> err出力とエラーを別ファイルに振り分け./scan.sh > report.txt 2> error.log

正常メッセージとエラーメッセージを別々のファイルに振り分けるスクリプトを作ります。

vi job.shjob.shを開き、iで挿入モードに入って、echo "完了"を標準出力に、echo "警告あり" 1>&2を標準エラーに出すスクリプトを書いてください(先頭に#!/bin/sh)。書けたらEsc:wqで保存します。

chmod +x job.shで実行権限を付け、./job.sh > out.txt 2> err.txtで出力とエラーを別ファイルに振り分けてください。

cat out.txtcat err.txtを実行し、正常メッセージとエラーメッセージがそれぞれ別のファイルに入っていることを確認してください。

④ 書く内容に迷ったら、解答パネルの本文をコピーしてviの挿入モードに貼り付けられます。

Linux console
0 / 3 実行済み
Loading Linux Terminal...
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1n=$(grep -c error log.txt)は変数 n に何を入れますか?

Q2if [ "$n" -ge 2 ]; then …は何をしますか?

Q3./scan.sh > report.txt 2> error.log2>は何を振り分けますか?