Pull to refresh

Comments 34

UFO landed and left these words here
Хм, возможно, Вы правы. Надо проверить работоспособность подобного решения.
Ваш метод немного отказоустойчивей
Статья расчитана на начинающих, которые впервые слышат буквосочетание FIFO применительно к Linux.
Поправте пожалуйста — … применительно к bash.
Просто Linux != bash.
Конкретно для Linux эту задачу решает incron
Как мне посоветовал telomejtel, также может подойти просто inotify. Incron работает, как я понимаю, на нем.
В моем посте же написано самое простое рукотворное решение из подручных средств.
А что мешало создать один скрипт, в котором сделать обработку в цикле, используя тот же sleep?
Потому что
а). Неизвестно, сколько будет файлов
б). Неизвестно, сколько займет обработка (от 40 минут до суток)
в). Неизвестно, когда придет еще один файл
Не вижу сложностей, чтобы сделать такой скрипт на циклах и sleep.
И что с того? Всё это неизвестно и сейчас, но почему цикл со sleep'ом хуже справился бы с этой задачей чем три скрипта — так и не ясно.
А чем flock не угодил? Ощущение, что изобрели велосипед
С lock-файлом мне удобнее работать.

Ощущение, что почти любой скрипт является велосипедом.
Жмем случайно на ребут во время выполнения скрипта… И лок файл висит вечно.
Здесь я согласен. В процессе поиска решения. Может, у Вас есть уже готовые строчки?
Можно попробовать не просто пустой лок, а, скажем, писать в него pid текущей задачи.
А при попытке входа — проверять наличие /proc/$pid.

Но на практике тут тоже возможны коллизии, покуда пиды заданий не бесконечны и реюзаются.
Думаю, flock действительно справиться с этой проблемой. Доберусь до машины — проверю.
> А при попытке входа — проверять наличие /proc/$pid.

Хотя в задаче не описаны требования, но так будет непереносимо, например, на фре proc может не быть, а в солярисе другой формат.

Есть интересный способ — послать сигнал 0 (ноль). Если процесс существует, то вернется тру.
Правда, требует прав на отправку сигнала процессу.

Ну, тут в любом случае «серебряной пули» не получится. Всё будет затачиваться на конкретную платформу.
На практике «на данной конкретной платформе» получится просто и компактно. Для теоретиков :).
А как бывает при попытке охватить все случаи, можно увидеть, например, рассматривая код межпроцессного лока в apache (Хоть там и не sh, но смысл тот же).
Тогда лучше посылать не ноль (его вернёт любой процесс), а сделать свой обработчик пользовательского сигнала, который вернёт заранее заданную магическую константу.
(при перезагрузке никто не гарантирует, что под заранее записанным пидом окажется именно свой процесс, а не какой-то иной. А такой handshake позволит его узнать)
> Ну, тут в любом случае «серебряной пули» не получится.
Совсем в любом не получится, но работа с сигналами это POSIX, а значит работать будет почти везде. А вот наличие и формат /proc вам никто не гарантирует. Посыл был такой =)

> который вернёт заранее заданную магическую константу.
Я таки извиняюсь, каким образом вы кому-т вернете из обработчика сигнала какую-то константу?
Блин, ну что за буквоедство!
Переформулирую, раз вас расстраивает слово «вернуть»: «как-то просигналить». Поменять состояние какого-нибудь условного объекта, доступного обоим процессам (например, «тронуть» «магический файл» — но это уже лишние детали реализации).

К тому же это в любом случае некритичная часть (ну, просто изначальная ситуация, о чём вся речь, достаточно гипотетическая. Никто в здравом уме не выключает компьютер reset-ом. А если такое случается, то гораздо проще проинициализировать всю систему во время стартапа оси, чем устраивать параноидальную проверку всего и вся при каждом чихе. Впрочем, от требований зависит, конечно).

А «серебряная пуля» для всех систем всё равно не выйдет. Банальный раздел /home на каком-нибудь vfat — и всё, уже приплыли.
Не переживайте вы так, все будет хорошо )
Я просто ежедневно сталкиваюсь с работой процессов, использующих локи и такие проверки, в том или ином виде, и делюсь с вами тем, что видел и возможными решениями.
То, что вы считаете лишними деталями реализации, чаще всего и «стреляет» (дьявол в мелочах!). Например, тач файла после проверки существования пида уже не атомарная операция, и это уже проблема. А еще недавно было, кстати, пид файл создан, но место на диске кончилось и процесс не записал туда пид.
Конечно, все зависит от требований к надежности.
Пули нет, но есть решения лучше, и есть хуже.
Вообще, «делай хорошо, а плохо само получится» )
flock -w 0 /tmp/.{jobs_medvoodoo или любое имя для идентификации}.lock {вызов скрипта} & как то так, и у вас пока процесс не закончится новый не вызовется. *фигурные скобки здесь в качестве ограничителя поля, в скрипте они не нужны.
Лок-файл нужно в /tmp делать чтобы не было таких проблем с перезагрузкой.
А удаление лок-файла или прочий «функционал десктруктора» зачастую комфортнее оформлять в обработчик trap. На случай какого-нибудь несанкционированного поведения «задачи».
Да и при санкционированном тоже (один раз вставил обработку — и всё, она есть; к концу уже не забудешь)
Заинтересовали две строки на Баше. Никогда ими не пользовался; такое ощущение что зря. Может пояснит кто?

FILES_LIST=( ... )

${FILES_LIST[@]}
FILES_LIST=( $(ls $HOME/jobs/Input) )

Здесь мы присваиваем переменной FILES_LIST как массиву содержимое папки. Получаем, что FILES_LIST — массив (обращение к которому идет так
${FILES_LIST[0]}, ${FILES_LIST[1]}, etc...

А про
${FILES_LIST[@]}

могу сказать, что это — просто весь массив как элемент. Если сделать
echo ${FILES_LIST[@]}

то выведется весь массив как объект. Я использую это в том контексте, что пускаю через весь массив цикл for.
Спасибо. Интересно что простое echo $FILES_LIST печатает только первый элемент списка. Не понимаю кому могло понадобиться такое поведение, ну да и ладно.
Думаю, flock — вам подойдёт гораздо больше для флага, что кто-то уже работает. Не надо на баше писать свой flock — всё равно плохой получился. Да и очередь тоже не вижу чтобы очищалась. После ребута пойдёте заново все задания выполнять из файлика?
Лучше почитайте что такое очередь.
Во-первых к сожалению после ребута ничего не будет.
Во-вторых пайп на то и пайп, что если из него взяли что-то, его там уже не будет. Да и на диск ничего не пишется.
вот потому-то и возникает вопрос обоснованности решения с очередью.
Мне кажется проще было-бы так —
каталоги Input, Work, Done.
Скрипт смотрит каталог Work. Если там что-то есть, то запускает выполнение, а потом переносит файл в Done. Если нет, то перемещает туда один файл из Input. работу с лок-файлами добавить по вкусу.
Решение ничем не хуже, но при этом очередь переживает перезагрузку без проблем. Потому как очередью является сам каталог Input.

Я бы еще сделал nohup перед строчкой с & в скрипте отправляющий задания
Sign up to leave a comment.

Articles