Почему этот inotifywait shellscript делает покупки с двумя PID?
Я учусь использовать inotifywait, в частности, используя скрипт по адресу: https://unix.stackexchange.com/questions/24952/script-to-monitor-folder-for-new-files. Что я не понимаю, так это то, почему мои скрипты всегда появляются два раза, когда я использую 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
Почему процесс сценария появляется два раза? Есть ли где-то вилка в процессе? Может ли кто-нибудь объяснить, почему именно происходит такое поведение двух процессов?
1 ответ
Потому что у него есть трубопровод.
Трубопровод разветвляется на подоболочку - второй процесс - и соединяет их. В случае 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
не позволяет содержать строки нестандартного формата \0
NUL-разграничить их, получить совершенно однозначный вывод из этого довольно сложно; это было рассмотрено в других ответах на Stackru, и я не сильно склонен воспроизводить их содержимое здесь.