Я просто прыгаю в Unix из другого мира, и хотел знать, если
while true
do
/someperlscript.pl
done
В самом скрипте perl есть средство просмотра папок / файлов, которое выполняется при изменении файлов в целевом местоположении.
Это while true
хорошая идея? Если нет, то какой предпочтительный надежный подход?
ТИА
РЕДАКТИРОВАТЬ: так как это, кажется, вызвало немало интереса, вот полный сценарий. Сценарий perl сам просматривает каталог с помощью средства просмотра файлов. Получив новые файлы (они поступают через rsync), он выбирает новый и обрабатывает его. Теперь входящие файлы могут быть повреждены (не спрашивайте ... поступающие от Raspberry Pi), и иногда процесс может не справиться с этим. Я не знаю точно, почему, потому что мы еще не знаем всех сценариев.
НО - если процесс по какой-то причине завершается неудачно, мы хотим, чтобы он был запущен и работал со следующим файлом, потому что следующий файл полностью не связан с предыдущим, что могло вызвать ошибку.
Обычно я бы использовал какой-то вид перехвата всех и обернул весь код так, чтобы он НИКОГДА не падал. Но не был уверен в Perl.
Из того, что я понял, использование чего-то вроде супервизора является хорошим подходом для этого.
inotify
API, чтобы избежать циклов занятости, ожидающих изменения файлов в вашей целевой директории.Ответы:
Это зависит от того, насколько быстро возвращается скрипт perl. Если он быстро возвращается, вы можете вставить небольшую паузу между выполнениями, чтобы избежать загрузки процессора, например:
Это также предотвратит загрузку процессора, если скрипт не найден или сразу завершится сбоем.
Цикл также может быть лучше реализован в самом скрипте perl, чтобы избежать этих проблем.
Редактировать:
Поскольку вы написали цикл, единственной целью является перезапуск сценария perl в случае его сбоя, лучшим подходом было бы реализовать его как отслеживаемую службу, но точный способ сделать это зависит от ОС. Например: Solaris smf, системный Linux или перезапуск на основе cron.
источник
while sleep 1; do ...
чтобы сохранить истинный вызов.until ! sleep 1; do ...; done
все равно сохранит этот встроенный вызов при немедленном запуске сценария.sleep 1& /someperlscript.pl; wait
.until
инструкцию, я перепутал ее с гипотетическимdo/until
циклом, которого нет в оболочке.Другие ответы, касающиеся использования
inotify
, являются правильными, но не являются ответом на этот вопрос.Супервизор процесса, например
supervisord
,upstart
илиrunit
, предназначен именно для проблемы смотреть и перезапуск службы , если он выходит из строя.Ваш дистрибутив, вероятно, поставляется с встроенным супервизором процесса.
источник
while true
хороша как универсальная конструкция "петля навсегда". Как говорят другие ответы, тело цикла не должно быть пустым или становиться пустым из-за того, что команда внутри цикла не работает.Если вы используете Linux, вы можете использовать команду вроде
inotifywait
, которая делаетwhile
цикл намного проще:Здесь
inotifywait
команда будет сидеть и ждать, когда произойдет событие файловой системы (в этом примере, когда файлы в каталоге записываются). В этот момент он успешно завершается, и тело цикла выполняется. Затем снова возвращается к ожиданию. Посколькуinotifywait
команда ожидает, что что-то произойдет в каталоге, она намного эффективнее, чем постоянный опрос каталога.источник
Переместите while 1 в сценарий perl (после предложения @roaima)
источник
Если ваш Perl-скрипт предназначен для постоянной работы, зачем использовать конструкцию while? Когда Perl не удается из-за какой-то серьезной проблемы, новый скрипт Perl, запущенный в то время как может произойти сбой так же сложно. Опять-и-снова и так далее.
если вы действительно хотите, чтобы ваш perl начинался заново, рассмотрите crontab и скрипт, который сначала проверяет наличие запущенных экземпляров. Таким образом, ваш скрипт будет запущен даже после перезагрузки.
источник
В общем случае проблем с использованием нет,
while true
поскольку это крошечный тест, который выполняется только после завершения сценария perl. Имейте в виду, что в зависимости от того, какой вариант Linux / Unix вы используете, скрипт может завершить работу при выходе из системы. В таком случае рассмотрите возможность использования цикла в скрипте, вызовите егоnohup
и поместите в фоновом режиме, т.е.nohup myscript &
Если сценарий perl завершается слишком часто и вызывает нагрузку на процессор, то эта загрузка отвечает за сценарий perl, а не за
while true
.Смотрите также
man nohup
для деталей.источник
Если вы хотите управлять процессом, вы можете обратиться к менеджеру процесса, чтобы сделать это.
Во многих современных системах вы можете использовать systemd для мониторинга ваших процессов (что является одним из преимуществ systemd по сравнению с классическими init-скриптами). Если ваш дистрибутив выбора не использует Systemd, вы могли бы использовать DaemonTools или Monit .
источник
mon
это простая альтернатива, если неуклюжие громадности monit и systemd беспокоят вас так же сильно, как и меня.while
Цикл действительно не очень хорошая идея. Там нет никакого выхода - это просто вечно - статически . Любое количество вещей может измениться в окружающей среде, и это не будет затронуто - и это может быть плохо.Например, если исполняемый файл оболочки, ответственный за этот
while
цикл, обновлен, ядро не сможет освободить место на диске для старой версии, пока этот скрипт не закроется, потому что ему нужно поддерживать дескриптор в течение всего времени его работы. И это верно для любых файлов, которые оболочка может открыть по любой причине для запуска цикла - все они будут оставаться открытыми этимwhile
циклом до тех пор, пока он выполняется - навсегда.И если, не дай бог, утечка памяти где-нибудь в оболочке, выполняющей этот цикл - даже самую маленькую - она просто продолжит течь - статически . Он будет создан без контроля, и единственный выход - принудительно убить его, а затем запустить его заново, чтобы сделать то же самое позже.
Это действительно не тот способ, которым вы должны настроить фоновый процесс - по крайней мере, на мой взгляд. Вместо этого, как мне кажется, должна быть точка сброса - обновление скрипта и его состояния. Самый простой способ сделать это с
exec
. Вы можете заменить текущий процесс новым, сохранив тот же PID, но продолжая запуск нового процесса.Например, если ваш
perl
скрипт должен возвращать true после того, как он успешно обработал изменение файла в некотором отслеживаемом каталоге:...или что-то типа того. Что-то, что позволяет базовому механизму за циклом обновляться время от времени.
источник
Я проголосовал за некоторые из этих ответов, но у меня инстинктивно самые теплые чувства к ответу @ WalterA. Ну, я сделал, пока я не создал свой собственный ответ ...
Лично я бы хотел обновить скрипт Perl, чтобы он записывал описательную запись в журнале о сбое и отправлял предупреждение администратору.
Если сценарий Perl предназначен для продолжения работы в ожидании событий изменения из файловой системы, почему он не работает?
Если это не дает сбоя, почему вы беспокоитесь о том, чтобы обернуть его в скрипт, чтобы перезапустить его бесконечно?
Если есть проблема конфигурации или какая-то нарушенная зависимость, которая приводит к прерыванию Perl-сценария, простой перезапуск его снова и снова вряд ли заставит его внезапно начать работать.
Вы знаете определение безумия, верно? (делать одно и то же снова и снова, ожидая другого результата). Просто говорю. ;-)
источник