Я пытаюсь написать сценарий оболочки, который будет ожидать появления файла в /tmp
каталоге с именем, sleep.txt
и как только он будет найден, программа прекратит работу, в противном случае я хочу, чтобы программа находилась в спящем (приостановленном) состоянии, пока файл не будет найден. , Теперь я предполагаю, что буду использовать тестовую команду. Итак, что-то вроде
(if [ -f "/tmp/sleep.txt" ];
then stop
else sleep.)
Я новичок в написании сценариев оболочки, и любая помощь очень ценится!
shell-script
files
Мо Гайнц
источник
источник
$MAILPATH
.Ответы:
В Linux вы можете использовать подсистему ядра inotify, чтобы эффективно ожидать появления файла в каталоге:
(предполагается, что Bash используется для
<()
синтаксиса перенаправления вывода)Преимущество этого подхода по сравнению с фиксированным интервалом времени, как в
в том, что ядро спит больше. С такой спецификацией события inotify, как
create,open
сценарий, он просто запускается при/tmp
создании или открытии файла . При фиксированном интервале опроса вы тратите циклы ЦП на каждый шаг времени.Я включил
open
событие, чтобы также зарегистрироваться,touch /tmp/sleep.txt
когда файл уже существует.источник
inotifywait -e create,open --format '%f' --quiet /tmp/sleep.txt --monitor > /dev/null ; # continues once /tmp/sleep.txt is created/opened
?inotifywait
сам является циклом while и выводит строку каждый раз, когда файл открывается / создается. Так что вам нужно, чтобы цикл while прерывался при его изменении.sleep.txt
в какой-то момент времени. Таким образом, нет расы. Вопрос не содержит ничего, намекающего на сценарий, который вы имеете в виду.Просто поместите свой тест в
while
цикл:источник
sleep
- это количество секунд ожидания в каждой итерации - вы можете изменить это в зависимости от ваших потребностей.Есть несколько проблем с некоторыми из
inotifywait
основанных на этом подходах:sleep.txt
файл, который был создан сначала как временное имя, а затем переименован вsleep.txt
. Нужно соответствовать дляmoved_to
событий в дополнение кcreate
sleep.txt
, был ли создан файл . Что, еслиfoo\nsleep.txt\nbar
файл был создан, например?inotifywait
как был запущен и установлен часы? Тогдаinotifywait
будет ждать вечно файл, который уже здесь. Вам нужно убедиться, что файл уже не существует после установки часов.inotifywait
запущенными (по крайней мере, до тех пор, пока не будет создан другой файл) после того, как файл найден.Для решения этих проблем вы можете сделать:
Обратите внимание, что мы наблюдаем за созданием
sleep.txt
в текущем каталоге.
(так что вы сделали быcd /tmp || exit
раньше в своем примере). Текущий каталог никогда не изменяется, поэтому, когда эта конвейерная линия успешно возвращается, она находитсяsleep.txt
в текущем каталоге, который был создан.Конечно, вы можете заменить
.
на/tmp
вышеприведенное, но во времяinotifywait
работы его/tmp
можно было бы переименовать несколько раз (маловероятно/tmp
, но в общем случае нужно что-то учитывать) или смонтировать на нем новую файловую систему, поэтому, когда конвейер возвращается, он может не быть/tmp/sleep.txt
, который был создан, но/new-name-for-the-original-tmp/sleep.txt
вместо этого. В/tmp
этом интервале также мог быть создан новый каталог, который не будет просматриваться, поэтомуsleep.txt
созданный там каталог не будет обнаружен.источник
Принятый ответ действительно работает (спасибо maxschlepzig), но оставляет мониторинг inotifywait в фоновом режиме, пока ваш скрипт не завершится. Единственный ответ, который точно соответствует вашим требованиям (т.е. ожидание появления sleep.txt внутри / tmp), кажется, что это Стефан, если каталог, который будет отслеживаться inotifywait, изменяется с точки (.) На '/ tmp'.
Однако, если вы хотите использовать ТОЛЬКО временный каталог для установки вашего флага sleep.txt и можете поспорить, что никто не будет помещать в него какие-либо файлы, достаточно просто попросить inotifywait просмотреть этот каталог для создания файлов:
1-й шаг: создайте каталог, который вы будете отслеживать:
2-й шаг: убедитесь, что каталог действительно есть
3-й шаг: дождитесь появления ЛЮБОГО файла внутри
$directoryToPutSleepFile
Файл, который вы
$directoryToPutSleepFile
вставите, может называться sleep.txt awake.txt, как угодно. В тот момент, когда какой-либо файл будет создан внутри$directoryToPutSleepFile
вашего скрипта, он продолжится послеinotifywait
оператора.источник
sleep.txt
создание между двумя вызовами inotifywait.sleep.txt
. Попробуйте, напримерtouch /tmp/foo /tmp/sleep.txt
, тогда один экземплярinotifywait
отчета сообщитfoo
и выйдет, и к тому времени, когда будет запущено следующее inotifywait, уже давно существует sleep.txt, поэтому inotifywait не будет обнаруживать его создание.в общем, довольно сложно сделать что-либо, кроме простого цикла тестирования / сна, надежным. Основная проблема заключается в том, что тест будет выполняться с созданием файла - если тест не будет повторен, событие создания может быть пропущено. На данный момент это лучшая ставка в большинстве случаев, когда вы будете использовать Shell для начала:
Если вы обнаружите, что этого недостаточно из-за проблем с производительностью, тогда использование Shell, вероятно, не является хорошей идеей.
источник
На основании принятого ответа maxschlepzig (и идеи из принятого ответа на /superuser/270529/monitoring-a-file-until-a-string-is-found ) я предлагаю следующее улучшение ( на мой взгляд) ответ, который также может работать с таймаутом:
В случае, если файл не был создан / открыт в течение заданного времени ожидания, состояние выхода будет 124 (согласно документации по времени ожидания (страница руководства)). В случае, если он создан / открыт, статус выхода равен 0 (успех).
Да, inotifywait запускается в под-оболочке таким образом, и эта под-оболочка будет работать только тогда, когда истечет время ожидания или завершится основной сценарий (в зависимости от того, что наступит раньше).
источник