質問
私はかなり定期的にいくつかのものが書かれているシェルスクリプトを書いています
そのファイルを読み込んで、アプリケーションが実行された後のファイルに。私たちの会社を介して、ネットワークの待ち時間が大幅に異なることがわかり、とても例えば、単純なsleep 2
は十分に堅牢ではありません。
私はこのような(設定)タイムアウトループを記述しようとした。
waitLoop()
{
local timeout=$1
local test="$2"
if ! $test
then
local counter=0
while ! $test && [ $counter -lt $timeout ]
do
sleep 1
((counter++))
done
if ! $test
then
exit 1
fi
fi
}
このはtest="[ -e $somefilename ]"
のために動作します。しかし、存在をテストすることは十分ではありません、私は時々、特定の文字列がファイルに書き込まれたかどうかをテストする必要があります。私は試した
test="grep -sq \"^sometext$\" $somefilename"
が、これは動作しませんでした。誰かがその理由を教えてもらえます?
このようなテストを実行するには、他の、より少ない冗長オプションがありますか?
解決
あなたは、あなたのテスト変数をこのように設定することができます:
test=$(grep -sq "^sometext$" $somefilename)
あなたのgrep
が働いていない理由は、引用符を引数に渡すことは本当に難しいということです。あなたはeval
を使用する必要があります:
if ! eval $test
他のヒント
私が言うと思います、テキストファイル内の文字列をチェックするための の方法は、grepのです。
これであなたの正確な問題は何でしょうか。
また、あなたは根本的な問題を取り除くために、あなたのNFSパラメータをマウント調整するかもしれません。同期にも役立つかもしれません。 NFSのドキュメントを参照してください。
あなたは「あれば」、あなたは「リターン」に「終了」を変更する場合がありますので、スクリプトの残りの部分は、エラー状況を処理することができます(偶数メッセージはありませんでwaitLoopを使用することを希望している場合スクリプトは、それ以外の場合は死ぬ前に)失敗したかについて、ユーザーます。
他の問題は、コマンドを保持するために、「$テスト」を使用していることは、あなたが実際には評価し、実行するシェル拡張を取得しないことを意味します。あなたが言うのであれば、テスト=「はgrepの\」のfoo \「\ 『バーバズ\』」、7文字の名前バーバズとファイルの3つの文字列fooのを探しているのではなく、それが5つの文字の文字列を探します9つのchar型のファイル "バーバズ" で "foo" という。
あなたはシェル魔法、およびテストセット=「グレップ平方^ sometextます$ somefilename」を必要としない、またはあなたはシェルが処理するために取得することができます決めることができますいずれかだからのようなもので、明示的に引用します:
if /bin/sh -c "$test"
then
...
それはそれを開くことなく書かれているときを検出するために、ファイルの更新時刻を使用してみてください。
のようなものold_mtime=`stat --format="%Z" file`
# Write to file.
new_mtime=$old_mtime
while [[ "$old_mtime" -eq "$new_mtime" ]]; do
sleep 2;
new_mtime=`stat --format="%Z" file`
done
複数のプロセスが同時にファイルにアクセスしようとした場合、これは、しかし、動作しません。
私は正確に同じ問題を抱えていました。私はあなたのOPに含めるタイムアウト待ちに同様のアプローチを使用しました。しかし、私はまた、ファイルサイズのチェックが含まれています。ファイルが最後にそれを確認したので、サイズが増加していた場合、私は私のタイムアウトタイマーをリセットします。私が書いているファイルは、いくつかのギグことができるので、彼らは、NFSを介して書き込むためにしばらく時間がかかります。
これはあなたの特定のケースのためにやり過ぎかもしれないが、それを書いて行われた後、私はまた私の書き込み処理は、ファイルのハッシュを計算していました。私はMD5を使用しますが、CRC32のようなものは、あまりにも、働くだろう。このハッシュは、(複数の)読者にライタからブロードキャスト、及びリーダは、ファイルサイズが増加停止、およびb)ファイルの(新たに計算された)ハッシュがライターによって送信されたハッシュと一致する)まで待機した。
私たちは、同様の問題を持っていますが、さまざまな理由。私たちは、SFTPサーバに送信されるのファイルを、読んでいます。スクリプトを実行しているマシンは、SFTPサーバではありません。
ファイルのcksumのを行うには(スリープとループがあまりにも動作するだろうが)のcronでそれを設定されている私は何を行っています。古いcksumのが(ファイルが時間の決められた量のために変更されていない)現在のcksumのが一致したとき、私たちは、書き込みが完了していることを知っているし、ファイルを転送します。
ただ、余分な安全のために、私たちは決してバックアップを作成する前に、ローカルファイルを上書きしていない、とだけ転送ですべてのリモートファイルが一致した行の2 cksumsを有する場合には、そのcksumのは、ローカルのファイルと一致していません。
あなたはコード例が必要な場合は、私はそれらを掘ることができると確信しています。
シェルは、言葉にあなたの述語を分割されました。以下のコードのように、それ$@
を持つすべてのグラブます:
#! /bin/bash
waitFor()
{
local tries=$1
shift
local predicate="$@"
while [ $tries -ge 1 ]; do
(( tries-- ))
if $predicate >/dev/null 2>&1; then
return
else
[ $tries -gt 0 ] && sleep 1
fi
done
exit 1
}
pred='[ -e /etc/passwd ]'
waitFor 5 $pred
echo "$pred satisfied"
rm -f /tmp/baz
(sleep 2; echo blahblah >>/tmp/baz) &
(sleep 4; echo hasfoo >>/tmp/baz) &
pred='grep ^hasfoo /tmp/baz'
waitFor 5 $pred
echo "$pred satisfied"
出力:
$ ./waitngo [ -e /etc/passwd ] satisfied grep ^hasfoo /tmp/baz satisfied
あまりにも悪いtypescriptですが、リアルタイムでそれを見てのように興味深いものではありません。
[OK]を...これは少し奇抜です...
ファイルを管理している場合:あなたはここで「名前付きパイプ」を作成することができるかもしれません。 だから、(書き込みプログラムがどのように機能するかに応じて)あなたは、同期方式でファイルを監視することができます。
その最も単純でます:
名前付きパイプを作成します:
mkfifo file.txt
sync'd受信機を設定します:
while :
do
process.sh < file.txt
end
テスト送信者を作成します:
echo "Hello There" > file.txt
あなたのロジックがどこに行く「process.shは」です:送信者は、その出力を書いたまでこれをブロックします。理論的には作家のプログラムが変性する必要はありません....
WARNING:!レシーバが何らかの理由で実行されていない場合、あなたは送信者をブロックしてしまうことがあります。
わからないことは、ここにあなたの条件に合う、しかしに探して価値があるかもしれません。
または同期を避けるために、 'lsofを' としてみてください?
http://en.wikipedia.org/wiki/Lsofする
あなただけの他に何も(すなわち、書き込み処理が終了した)、それに書き込みを行っていないときにファイルから読みたいと仮定すると - あなたは他に何もそこにファイルハンドルを持っていないかどうかをチェックすることができます。
?