2012-03-12 7 views
10

В Ruby 1.9.x, что может быть простым способом либо не разрешить мой скрипт Ruby, либо дождаться окончания предыдущего экземпляра? **Как ограничить одновременные экземпляры одного и того же скрипта Ruby?

Я надеюсь избежать беспорядочной блокировки файлов или проверка таблицы процессов.

Есть ли что-то вроде global mutex или семафор уже в ядре? Я изучил родной Mutex, но это, похоже, применяется только к потокам в рамках одного процесса Ruby, а не к различным процессам.

** Впоследствии я мог бы добавить функции тайм-аута или ограничить N экземплярами, или попытаться использовать более одной глобальной блокировки (по одному на общесистемный ресурс, который должен иметь только один экземпляр).

ответ

2

Обычно это решается на уровне ОС, проверяя флаг-файл и не пытающийся запускать его снова, а не в самом скрипте.

Но если вы хотите проверить скрипт, найдите файл семафора в известном месте. Если он существует и не находится в заданном временном окне, которое соответствует вашему окну запуска, удалите его и создайте новый. Если он находится в вашем окне времени, то выйдите.

Вы можете использовать блокировку файлов или хранить метки времени в файле или многие другие проверки, если вы не запускаете механизм cron-типа. Каждый подход имеет свои плюсы и минусы.

Вы хотите захватить прерывания, чтобы при выходе из Control-C вы также удалили этот файл.

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

+0

Я уже переношу большую часть своих Ruby с помощью скриптов Bash, которые сами используют код типа '[-z" $ (pidof -x -o% PPID -o $$ $ {0 ## * /}) "] || exec echo "$ (date) $ 0: $$ уже пахнет PID: $ (pidof -x $ 0), ... bye !!", однако это служит другим целям. Еще лучшее решение, уже содержащееся в Ruby, заключается в блокировке любого фиксированного файла для записи, например. '/ TMP/scriptname.rb.lock'. При выходе или даже при сбое моего кода (который часто вызывает исключения) система очистит эту блокировку. Я просто займусь этим взломом, пока не будет чистого, родного интерфейса с глобальными семафорами, и мне все равно понадобится. – Marcos

5

Это очень короткий код не будет замерзать на месте, пока файл блокировки в/TMP имени вашего скрипта заблокирован исключительно:

File.open("/tmp/#{File.basename $0}.lock", File::RDWR|File::CREAT, 0644).flock(File::LOCK_EX) 

Любая другая программа блокирует его, Ruby или нет, нужно только прекратить или быть убитым , чтобы новый экземпляр процесса разблокировался и продолжался. Так что пока это обходное решение делает то, что мне нужно. Я могу назвать свою программу на Ruby с

timeout 1m ./myrubyscript.rb 

из оберточных Баша сценария, если я нетерпелив, например. (В этом примере myrubyscript.rb закончится через 1 минуту независимо от того, был ли он заблокирован файлом, чтобы продолжить выполнение того, что он написал.)

Смежные вопросы