
スクリプトを使用してファイルを観察し、60秒ごとにファイルのmd5sumを比較して変更された場合は、画面に警告を印刷してみてください。
何をすべきかわかりません。それが私が持っているのですが、少し外れたようです。
#/bin/bash
watch=$@
if [ -z "$watch" ]
then
echo "No file specified, aborting"
exit
else
echo "watching : $watch"
fi
while [ 1 ]; do
watch -n 60 -d md5sum $watch
done
私もこれを行いましたが、うまくいくようです(一種の)。ファイルが変更されたかどうかを通知しますが、watchコマンドを使用しません。ウォッチでこれを行う方法はありますか?
#/bin/bash
watch=$@
if [ -z "$watch" ]
then
echo "No file specified, aborting"
exit
else
echo "watching : $watch"
fi
checksum1="empty"
while [ 1 ]; do
checksum2=$(md5sum $watch | md5sum | cut -d ' ' -f1)
if [ "$checksum2" != "$checksum1" ];
then
echo "Warning : $watch has been changed"
#mail -s "$watch has been changed" "[email protected]"
echo -e "\a"
fi
checksum1="$checksum2"
sleep 60
done
答え1
あなたははるかに良い状況にありますinotify、これはファイル監視という目的で作成されました。
編集する:リンクされた質問に対する回答をここにまとめます。
ファイルやディレクトリを監視する必要があるときはいつでも、inotifyはその操作に適したツールです。監視したいイベント(ファイルへのアクセス、変更、開く、閉じる、削除など)をinotifywaitに通知できます(man inotifywait
詳細を見る)。
最初の方法は次のループです。
while inotifywait -e close_write myfile.py; do ./myfile.py; done
最大の欠点は、イベントを見逃すことができることです。より効率的なバージョンは次のとおりです。
inotifywait -mq --format '%e' /path/to/file |
while IFS= read -r events; do
/path/to/script "$events"
done
この後者のバージョンでは、イベントを見逃すことはありません。パイプはイベントがキューに入っていることを確認します。ループが時間内に選択されていない場合は積み重ねられますが、欠落している項目はありません。
編集する:テキストファイルを追跡する場合は、強力なハッシュを使用してファイルを追跡するので、gitもお勧めします。以下はメインループのbash擬似コードですinotify
:
git status file # Tells whether <file> was modified
if file was modified; then
git commit -- file # Add <file> to the repository
keep only the last two versions of <file>
print the warning message
fi
これをベースとして使用できます。たぶん、git
出力を解析する必要があります。私はあなたに正しい方法を話すのに十分に使用していませんが、それがトリックを実行できるような直感があります;-)。
答え2
私はこの答えを嫌いますが、約15分間この答えで遊んだ後は、コマンドでそれを達成する方法がないと思います。watch
(他の人は私が間違っていることを証明してください。)
問題は、watch
独自のループで独自に実行され、シェルへのデータの供給を中断することなく、独自のエコーのみを提供することです。
watch
run がどのように動作するかによって、どのようなif
or while
check ステートメントでもこれを使用すると、シェルが結果を返さないため、変更を評価する機会は提供されません。ループを手動で終了するまでこれを保持します。
2番目の例のように、独自のループを実行してmd5sumをチェックすることは、目的のタスクを実行するための最良の方法です。
たとえば、質問
echo `watch -d md5sum testfile.txt`
エコーは決して消えません。エコーが端末に到達する方法を見つけることができれば、それスクリプトを実行する答えです。
答え3
ファイルパラメータを提供し、md5sumを使用するというアイデアに従うこの粗雑なスクリプトを試してください。 md5sumが変更されるたびにタイムスタンプが表示された行が表示され、ログファイルが保存され、ctrl-cを押すと停止します。コンテンツwatch_and_notify.sh
:
#!/bin/bash
logf="$1.log"
interval=2
first_run=
# temp files, current and last md5s for diff to compare
lm1="$(mktemp /tmp/lm1.$$.XXXX)"
lm2="$(mktemp /tmp/lm2.$$.XXXX)"
if [ -z "$1" ]; then
echo "No file specified, aborting" >&2
exit 1
fi
echo "Watching at ${interval}s intervals: $1"
# loop forever until cancel this script
while true; do
md5sum "$1" > $lm1
# otherwise in the first iteration,
# lm2 does not yet exist, so diff
# will always unintentionally report
# a difference when comparing existing
# file with nonexisting file
if [ -z "$first_run" ]; then
cp -a $lm1 $lm2
first_run=1
fi
# test ! to invert usual exit code
if ! diff $lm2 $lm1; then
echo -e "$(date +"%F %R")\tChange detected:\t$1" | tee -a "$logf"
fi
# rotate
mv $lm1 $lm2
sleep $interval
done
# when you ctrl-c it should garbage cleanup
trap "rm $lm1 $lm2; exit 1" SIGINT
はい
次の名前の空のテキストファイルを起動します。a.txt
$ touch a.txt
次のようにスクリプトを実行し、以下を確認してください。
$ ./watch_and_notify.sh a.txt
Watching at 2s intervals: a.txt
2番目の端末では変更をテストします。
$ echo addition >> a.txt
最初の端末でスクリプトを実行すると、アップデートが表示されます。
Watching at 2s intervals: a.txt
1c1
< d41d8cd98f00b204e9800998ecf8427e a.txt
---
> 9913e6909c108b5c32c69280474b2b2a a.txt
2015-09-29 15:56 Change detected: a.txt
2番目の端末で別の変更を適用します。
$ echo anotherchange >> a.txt
その後、スクリプトを実行する最初の端末で出力が再度更新されます。
Watching at 2s intervals: a.txt
1c1
< d41d8cd98f00b204e9800998ecf8427e a.txt
---
> 9913e6909c108b5c32c69280474b2b2a a.txt
2015-09-29 15:56 Change detected: a.txt
1c1
< 9913e6909c108b5c32c69280474b2b2a a.txt
---
> 5c1c20a75b9982128f8300a7940f9ce0 a.txt
2015-09-29 16:06 Change detected: a.txt
あなたはやめましたctrl-c
。コマンドプロンプトに戻ります。コンテンツを一覧表示し、ログがあることを確認します。
$ ls -lh
total 12K
-rw-r--r-- 1 meme meme 22 Sep 29 16:06 a.txt
-rw-r--r-- 1 meme meme 80 Sep 29 16:06 a.txt.log
-rwxrwxrwx 1 meme meme 775 Sep 29 15:26 watch_and_notify.sh
ログを見ると、変更の瞬間を記録するのと同じタイムスタンプ項目が表示されます。
$ cat a.txt.log
2015-09-29 15:56 Change detected: a.txt
2015-09-29 16:06 Change detected: a.txt
コードの説明
全体的な流れのほとんどはスクリプト内のコメントを見ると分かりますが、基本的にファイルに対してmd5sumコマンドを繰り返し実行しながら結果を保存して回転させ、プログラムが現在の結果を以前の繰り返し結果diff
と比較するようにします(もしすべて)。レポート操作を実行します。この場合、これらのジョブはタイムスタンプとともに画面に出力され、ログに追加されます。ユーザーはctrl-cを使用してスクリプトを停止し、差が検出されたタイムスタンプの瞬間にログを残します。
スクリプト内で
lm1="$(mktemp /tmp/lm1.$$.XXXX)"
lm2="$(mktemp /tmp/lm2.$$.XXXX)"
- lm1 と lm2 は、比較のために md5sum 出力を保存するために使用される一時ファイルであり、スクリプトの実行時にのみ生成されます。
- あなたが言ったように、重要な方法は文字通りmd5sumを比較するので、そのために最初に保存する一時的な場所を定義します。
mktemp
一意の一時ファイル名を作成するのに役立ちます。$$
現在のプロセスIDで、ランダム性を追加します。XXXXX
各文字を任意の英数字にmktemp
置き換えるように指示します。X
したがって、実行時に /tmp に、定義したパターンで指定されたファイルが 1 つ以上含まれていることを確認できます。
$ ls -lh /tmp/lm*
-rw-r--r-- 1 meme meme 40 Sep 29 15:08 /tmp/lm2.8248.xGJTl
次に、whileループがあります。
# loop forever until cancel this script
while true; do
...
done
ほとんどのコードは大きなwhile <command>; do ... done
ループにはめ込まれています。コマンド/条件はtrue
常にtrueなので、このコードは停止するまで無期限に実行されますctrl-c
。
各ループ反復は、まず現在の反復のmd5sum結果を生成して保存します。
md5sum "$1" > $lm1
$1
最初の位置パラメータを示します。この場合、実行すると次のようになりますwatch_and_notify.sh a.txt
。$1
a.txt
> $lm1
前に定義した一時ファイルへの出力の書き込み
初めて実行すると、以前の反復はありません。ただし、コマンドはdiff
以前のmd5sum結果の変更を$lm2
比較する必要があるように配置されています$lm1
。これは、最初の実行では常に誤って違いを示すため、最初の実行では特別な条件付き操作が必要です。最初の実行を認識できるように、while
ループの前に定義された初期空の変数を作成します。
first_run=
次に、ループ内で次をテストします。
if [ -z "$first_run" ]; then
cp -a $lm1 $lm2
first_run=1
fi
-z
0 値をテストします。最初の繰り返しの場合は、$ first_runは常に空なので、そのthen
セクションに進んでください。- この
then
セクションでは、「前の繰り返し」をコピーして「偽」にします。$lm1
したがって、後でdiff
最初の反復では、2つの同じファイルを比較し、違いは報告されません。 first_run=1
これにより、次の反復ではif [ -z "$first_run" ]; then
ゼロ$first_run
値ではなくなり、このthen
部分はトリガーされないため、この操作は最初の反復でのみ実行されます。
diff
次に、前の反復のmd5sum結果(変数で参照されるファイルに保存されている)$lm2
と現在の反復のmd5sum結果(変数で参照されるファイルに保存されている)とを比較する実際の条件があります。$lm1
if ! diff $lm2 $lm1; then
diff
私たちはコマンドの終了コードに反応することに頼っています。diff file1 file2
同じ場合、通常は終了コード0が発生します。実行時にこれをテストすると、ゼロ$ diff a.txt a.txt; echo $?
が表示されます。異なる場合、$ diff a.txt b.txt; echo $?
たとえば、b.txt
異なる結果があるでしょう。1
- しかし、
0
bashはその意味が次のようtrue
に1
なると思います。false
- したがって、ファイルが同じ場合は次のように解釈され、セクションをトリガーする終了コード0を提供する
if diff $lm2 $lm1; then
ため、これを行うことはできません。diff
true
then
- 私たちは反対の行動を望み、同じなら何もせず、違うと何かをします。
!
出力反転ヘルプ
したがって、変更をテストできます。
変更が発生した場合の対処方法は次のとおりです。
echo -e "$(date +"%F %R")\tChange detected:\t$1" | tee -a "$logf"
echo
-e
レンダリングを\t
タブとして使用date +"%F %R"
現在のタイムスタンプを指定された形式でレンダリングします(例:2015-09-29 15:56)。|
tee
プログラムによるパイプ出力tee
発生した変更に関する出力メッセージを表示し、出力を保存できます。-a
保存方法をさらに設定してください。それ以外の場合は、結果があるたびに前の結果が上書きされます。
現在の繰り返し作業はほぼ完了している。diff
比較と操作が完了した後、次の反復を準備するために、次の手順を実行します。
mv $lm1 $lm2
mv
$lm1
に保存されている現在の繰り返しのmd5sum結果をからに移動するか、名前を変更します$lm2
。- したがって、
diff $lm2 $lm1
次の反復では、実際に前の反復のmd5sumを比較します。
最後のループの最後の行は、sleep句sleep $intervalです。
sleep
$interval
変数として提供される結果の遅延(秒)$interval
ファイルの先頭に設定された変数は次のとおりです。2
したがって、各反復は2秒間続きます。
完璧
done
最後に閉じるwhile ...;do ... done
ループがあります。