1

特にhttps://unix.stackexchange.com/questions/24952/script-to-monitor-folder-for-new-filesのスクリプトを使用して、inotifywait の使用方法を学習しています。理解できないのは、 を使用すると、スクリプトが常に 2 回表示される理由pid xです。

36285 pts/1    S+     0:00 /bin/bash ./observe2.sh /home/user1/testfolder
36286 pts/1    S+     0:00 inotifywait -m /home/user1/testfolder -e create -e moved_to
36287 pts/1    S+     0:00 /bin/bash ./observe2.sh /home/user1/testfolder

テストを迅速に行うために、リンクされたスクリプトを変更して、 $1 経由で任意のフォルダーを渡して監視し、次のように保存できるようにしましたobserve2.sh

#!/bin/bash
inotifywait -m $1 -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        # do something with the file
    done

スクリプト プロセスが 2 回表示されるのはなぜですか? プロセスのどこかにフォークはありますか?2つのプロセスのこの動作が正確に発生している理由を誰かが説明できますか?

4

1 に答える 1

5

パイプラインがあるからです。

パイプラインは、サブシェル (2 番目のプロセス) をフォークし、それらを接続します。foo | bar-- これらが両方とも外部の非シェル コマンドである場合-- サブシェルexecは実際のコマンドを実行するため、プロセス ツリー エントリが失われます。そのパイプラインの要素をシェルで書くと、それを実行するシェルがプロセスツリーに残ります。


そうは言っても、[1]少し違った書き方をお勧めします。

while read -r path action file; do
    echo "The file '$file' appeared in directory '$path' via '$action'"
    # do something with the file
done < <(exec inotifywait -m "$1" -e create -e moved_to)

これにより、while ループがメイン プロセスに維持されexec、フォークされたサブシェルが に置き換えられinotifywaitます。したがって、whileスクリプトで変数を設定するなど、ループ内で行った変更は、スクリプトがループから移動した後も保持されますが、ループをパイプラインに配置すると、その中に設定された変数はすべてサブシェル。詳細については、 BashFAQ #24を参照してください。


[1] - 実際、すべてのコーナーケースを完全にカバーしたい場合は、それよりもさらに別の方法で書くことをお勧めします。POSIX ファイル名には NUL 以外の任意の文字を含めることができるため/(/もちろん、パス名に存在することもできます)、スペースまたは改行で区切られた名前は非常に悪い考えです。空白で終わる名前に関する既存の実装にもバグがあります。残念ながら、inotifywaitカスタム フォーマット文字列に NUL 区切りを含めることは許可されていないため\0、完全に明確な出力を取得することは非常に困難です。StackOverflow の他の回答でカバーされており、ここでその内容を再現する気はあまりありません。

于 2015-06-05T15:46:43.750 に答える