Обработка ошибок в сценарии оболочки

Я написал сценарий оболочки run_script.sh , который включает в себя шаг, который создает пустой файл run_script.lck . Каждый раз, когда скрипт оболочки вызывался cronjob, он проверяет наличие run_script.lck . Если блокировка присутствует, она указывает, что run_script.sh уже запущен и еще не завершен. Файл run_script.lck будет удален в конце программы.

Проблема заключается в удалении файла блокировки при сбое сценария оболочки и до его выхода.

Я написал такую ​​строку:

 trap "rm -f run_script.lck" EXIT 

Но он удалит файл блокировки в нежелательном состоянии следующим образом:

Я run_script.sh в оболочке A, и он запускается, файл блокировки был создан. Затем я выполняю его снова в оболочке B, и он сказал, что скрипт уже запущен, и скрипт будет прерван. Однако, поскольку ловушка получила сигнал EXIT, включая сигнал от оболочки B, который выходит из прерванного сценария, он удаляет файл блокировки. И скрипт в оболочке A все еще запущен, но блокировка была удалена, и любой может снова вызвать другой run_script.sh когда уже запущен один скрипт.

Любая идея, как это решить?

Чтобы проиллюстрировать ответ Игнасио (используйте следующий протокол: сначала проверьте, существует ли файл блокировки, а затем установите ловушку), вы можете решить проблему следующим образом:

 $ cat test2.sh if [ -f run_script.lck ]; then echo Script $0 already running exit 1 fi trap "rm -f run_script.lck" EXIT # rest of the script ... 

Перед установкой ловушки проверьте наличие замка.

В пути устанавливается ловушка ошибок и позволяет отменить сценарий в случае ошибок ( set -e ). Например

 $ cat test.sh set -e trap "echo foo" ERR if [ $# == 1 ]; then exit 0 fi false $ bash test.sh foo $ bash test.sh 1 $ 

(где $# – количество аргументов)

В вашем скрипте вам просто нужно убедиться, что вы выполняете команду trap, когда сценарий выполняется успешно (т. Е. Не происходит сбой, например, в конце вашего обычного потока программ).

set -e означает, что каждый статус выхода не равен 0 заканчивает выполнение скрипта. Подобно этому, при set -u каждое (возможно, случайное) использование неопределенной переменной завершает выполнение.

Таким образом, перенос этой идеи в исходный прецедент, решение может выглядеть так:

 $ cat test.sh set -e trap "rm -f run_script.lck" ERR if [ -f run_script.lck ]; then echo Script $0 is already running exit 1 fi # # do all the work ... # # no error until now rm -f run_script.lck