コマンドをテストして検索する場合、bashを使用するにはどうすればよいですか?


25

クラッシュログのあるディレクトリがあり、findコマンドに基づいてbashスクリプトで条件文を使用したいと思います。

ログファイルは次の形式で保存されます。

/var/log/crashes/app-2012-08-28.log
/var/log/crashes/otherapp-2012-08-28.log

最後の5分間に変更された特定のアプリのクラッシュログがある場合にのみifステートメントがtrueを返すようにします。find私が使用することをコマンドは次のとおりです。

find /var/log/crashes -name app-\*\.log -mmin -5

それをifステートメントに適切に組み込む方法がわかりません。私はこれがうまくいくと思う:

if [ test `find /var/log/crashes -name app-\*\.log -mmin -5` ] then
 service myapp restart
fi

不明な点がいくつかあります。

  • 私はifフラグを見ましたが、もしあれば、どれを使うべきかわかりません。
  • testディレクティブが必要ですか、それともfindコマンドの結果に対して直接処理する必要がありますか、それともfind... | wc -l代わりに行カウントを取得するために使用する必要がありますか?
  • この質問に答えるために100%必要というわけではありませんがtest、コマンドが返すリターンコードに対するテストのためですか?そして、それらは目に見えないようなものです- stdout/ stderr?このmanページを読みましたが、いつ使用するtestか、どのようにデバッグするかについてはまだはっきりしていません。

一般的なケースに対する本当の答えは使用することfind ... -execです。また、なぜfindの出力をループするのが悪い習慣の
ワイルドカード

@Wildcard-残念ながらそれ一般的なケースを解決しません:複数の一致があり、アクションを一度だけ実行する必要がある場合は機能せず、存在するときにアクションを実行する必要がある場合は機能しません一致しません。前者はを使用して解決できますが... -exec command ';' -quit、結果を解析する以外に後者の解決策はないと思います。また、どちらの場合でも、結果の解析に関する主要な問題find(ファイル名の文字と区切り文字を区別できないこと)は当てはまりません。これらの場合は区切り文字を見つける必要がないからです。
ジュール

回答:


27

[そして、test(除く同義語です[必要で]、使用したくないので、) [ test

[ -x /bin/cat ] && echo 'cat is executable'
test -x /bin/cat && echo 'cat is executable'

test条件が真の場合、ゼロの終了ステータスを返し、そうでない場合はゼロ以外を返します。これは実際には、終了ステータスを確認するためのプログラムに置き換えることができます。0は成功を示し、0以外は失敗を示します。

# echoes "command succeeded" because echo rarely fails
if /bin/echo hi; then echo 'command succeeded'; else echo 'command failed'; fi

# echoes "command failed" because rmdir requires an argument
if /bin/rmdir; then echo 'command succeeded'; else echo 'command failed'; fi

ただし、上記の例はすべて、プログラムの終了ステータスのみをテストし、プログラムの出力を無視します。

以下のためのfind任意の出力が生成された場合は、テストする必要があります。-n空でない文字列をテストします。

if [[ -n $(find /var/log/crashes -name "app-*.log" -mmin -5) ]]
then
    service myapp restart
fi

テスト引数の完全なリストはhelp testbashコマンドラインで呼び出して利用できます。

を使用しているbash(ではないsh)場合は[[ condition ]]、を使用できます。これは、条件にスペースまたはその他の特殊なケースがある場合により予測可能な動作をします。それ以外の場合、通常はを使用するのと同じ[ condition ]です。私が使ってきた[[ condition ]]私は可能な限りそうであるように、この例では。

また、に変更`command`しましたが$(command)、これも一般に同様に動作しますが、ネストされたコマンドの方が優れています。


echo失敗することがあります試してecho 'oops' > /dev/full
-derobert

この答えは問題の根底にあるすべてを打ち破りますが、それが何であるかを正確に言及することを優雅に避けます。
バハマ

9

findエラーがなかった場合は正常に終了します。そのため、ファイルが見つかったかどうかを知るために終了ステータスを当てにすることはできません。しかし、あなたが言ったように、見つかったファイルの数を数え、その数をテストすることができます。

次のようなものになります。

if [ $(find /var/log/crashes -name 'app-*.log' -mmin -5 | wc -l) -gt 0 ]; then
    ...
fi

test(別名[)はコマンドのエラーコードをチェックせず、テストを行うための特別な構文を持ち、テストが成功した場合はエラーコード0で終了し、そうでない場合は1で終了します。これはif、渡すコマンドのエラーコードをチェックし、それに基づいて本体を実行するものです。

man test(またはhelp testを使用する場合はbash)、およびhelp if(同じ)を参照してください。

この場合、wc -l数値を出力します。testのオプションを使用して-gt、その数がより大きいかどうかをテストします0。そうである場合、test(または[)は終了コードで戻ります0ifその終了コードを成功と解釈し、本体内でコードを実行します。


1

これは

if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5)" ]; then

または

if test -n "$(find /var/log/crashes -name app-\*\.log -mmin -5)"; then

コマンドtest[ … ]は同義語です。唯一の違いは、名前と、最後の引数として[終了を必要とするという事実です]。いつものように、コマンドの置換を二重引用符で囲みます。そうしないと、findコマンドの出力が単語に分割され、一致するファイルが複数ある場合(および引数がない場合[ -n ]はtrue)に構文エラーが発生します、[ -n "" ]どちらが偽かを知りたい場合)。

ksh、bash、およびzshでは使用できますが、ashでは使用できません。[[ … ]]解析規則は異なります。[通常のコマンド[[ … ]]ですが、構文解析構文は異なります。内部に二重引用符は必要ありません[[ … ]](ただし、二重引用符は問題ありません)。あなたはまだ;コマンドの後が必要です。

if [[ -n $(find /var/log/crashes -name app-\*\.log -mmin -5) ]]; then

これは潜在的に非効率的である可能性があります:に多くのファイルがある場合/var/log/crashes、findはそれらすべてを探索します。一致が見つかったらすぐに、またはその直後にfindを停止する必要があります。GNU find(非組み込みLinux、Cygwin)では、-quitプライマリを使用します。

if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5 -print -quit)" ]; then

他のシステムでは、最初の一致の直後に少なくとも終了findするheadようにパイプします(findは壊れたパイプで死にます)。

if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5 -print | head -n 1)" ]; then

(コマンドでサポートされているhead -c 1場合に使用できますhead。)


または、zshを使用します。

crash_files=(/var/log/crashes/**/app-*.log(mm-5[1]))
if (($#crash_files)); then


0
find /var/log/crashes -name app-\*\.log -mmin -5 -exec service myapp restart ';' -quit

ここで適切なソリューションです。

-exec service myapp restart ';'原因findあなたは、むしろ何かを解釈するためにシェルを必要とするよりも、直接実行することをコマンドを呼び出すために。

-quit原因となるfind条件に一致する複数のファイルがあることが起こる場合ので、再び実行されているコマンドを防止、コマンドを処理した後、出口へ。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.