Практическое задание

Эта задача — шаг 25 курса «Bash-скрипты: от цикла до надёжного скрипта»

Не дай скрипту запуститься дважды

сложно~12 мин

Скрипт /usr/local/bin/job.sh запускается по расписанию и иногда стартует, не дождавшись завершения предыдущего запуска — из-за чего задача выполняется параллельно сама с собой. Доработай скрипт, используя блокировку flock, так, чтобы второй одновременный запуск немедленно завершался с ненулевым кодом, ничего не сделав, а первый продолжал работу. Полезную нагрузку (запись строки в /var/lib/job/runs.log и паузу) оставь как есть. Открой скрипт во вкладке «Редактор» над терминалом: каталог /usr/local/bin открыт в ней.

Что потренируешь:
  • flock
  • блокировки
  • файловые дескрипторы
  • конкурентный запуск
  • exec N>

Разбор темы

flock берёт консультативную блокировку на открытый файловый дескриптор. Ключевое свойство — блокировку освобождает ядро при закрытии дескриптора, то есть при любом завершении процесса, включая аварийное; поэтому она не оставляет «залипших» замков, в отличие от самодельных pid-файлов. Флаг -n (non-blocking) заставляет вернуть ошибку вместо ожидания, что и даёт семантику «второй запуск не выполняется». Идиома exec 9>файл открывает дескриптор на всё время жизни скрипта, так что блокировка держится ровно столько, сколько идёт работа. Учти, что открытые дескрипторы наследуют дочерние процессы: если скрипт запустит что-то в фоне, этот потомок продолжит держать замок и после выхода самого скрипта — такие команды запускают с закрытым дескриптором (9>&-).

Что проверяется

  1. скрипт использует flock
  2. второй одновременный запуск завершается с ошибкой
  3. полезная нагрузка выполнилась ровно один раз

Как это выглядит