以下のコマンドは結果を与えていません。ファイルのエラー行をgrep
してテーブルに挿入したい。
機能していないコマンド:
tail -f logfile.log | grep ERROR|while read msg; do psql -d testdb -c insert into t values('$msg'); done
しかし、grep ERROR
コマンドからのコード、期待どおりに動作しています。何が起こっているのかわかりませんか?
正常に動作しているコマンド:
tail -f logfile.log|while read msg; do psql -d testdb -c insert into t values('$msg'); done
ファイルには以下のデータがあると想定できます。
ERROR
sql committed
ERROR
ERROR
error
...
2つのこと:
質問で記述されているように、コードはリテラル文字列$msg
を挿入します(機能する場合)。代わりに二重引用符を使用してください。ここでは、ステートメント全体を二重引用符で囲み、$msg
を展開します。シェルコードは、grep
からの結果に応じて、依然として脆弱です。 $msg
の文字列は、単一の'
または他の特殊文字がステートメントを壊さないように、適切にサニタイズするのが理想的です(または、さらに悪いことに ユーザーからのコメントcas以下 )。
tail -f logfile.log |
grep -F 'ERROR' |
while read msg; do
psql -d testdb -c "insert into t values('$msg')"
done
また、固定文字列を使用して検索しているため、-F
をgrep
呼び出しに追加しました(これは、主にドキュメント化の目的で)。
grep
は出力をバッファリングするため、出力バッファがいっぱいになるまで何も生成しません。これは実際には「機能しない」という印象を与えますが、grep
が出力バッファーをフラッシュして、十分なデータが入るまでは何もしません。これはパフォーマンスの最適化です。
GNU grep
(およびOpenBSDなどの同じユーティリティの他のいくつかの実装)は、--line-buffered
オプションを使用してラインバッファリングすることができます。
tail -f logfile.log |
grep --line-buffered -F 'ERROR' |
while read msg; do
psql -d testdb -c "insert into t values('$msg')"
done
注:現在PostgreSQL(?)インスタンスを実行していないため、これはテストしていません。