"Articles are my own, not views of my employer"

就活や転職に役立てるためTips投稿や競プロwriteupを行いプレゼンスを高める自分用備忘録です

他のプログラムの標準出力にしたがって動くシェルスクリプト

要約

他のプログラムにパイプで繋ぐことで,そのプログラムの標準出力を受け取り,出力にしたがって動くシェルスクリプトの作成方法.

要件

今回はパフォーマンス測定のためのツールとして作成した. ここでは,プログラム中のある点での /proc/meminfo を知りたいとしよう. このとき,プログラムを改変して,fork等呼び出せばできるがあまりにめんどくさい. よってここで決められた文字列(たとえば"meminfo_record")を出力することで,これを記録するような別のスクリプトを動作させることを考える. このとき,記録用のシェルスクリプト自体に時間を取られないことが肝要である.

まとめると以下.

  • パイプで起動(e.g. $ target_proc | measure.sh
  • 入力は基本teeみたいに受け流し.ただし特定入力(e.g. "meminfo_record")については別コマンド実行.
  • ポーリングではなく,イベント駆動

答え

#!/bin/bash

while read line
do
    echo "$line"
    if [ "$line" = "meminfo_record" ]; then
        break
    fi
done

cat /proc/meminfo > meminfo.log

ハマった落とし穴

whileの書き方によって無限ポーリングしてハマる.

while :
do
    read line
    echo "$line"
    if [ "$line" = "meminfo_record" ]; then
        break
    fi
done

バックグラウンドで測定開始,後に終了させる

今回はmeminfo一発で終わりだが,ここでパフォーマンス測定プロセスを開始し,後にそれを終了させたいような場合を考える. このとき,

  1. バックグラウンド実行
  2. PID取得
  3. シグナル送信

の3つのテクニックが鍵となる.

バックグラウンド実行

some_command &

PID取得

some_command &
pid=$!

シグナル送信

ここではC-cみたいなの.

kill -INT $pid