Вопрос или проблема
Мне нужно запустить несколько shell-скриптов последовательно (s1.sh, s2.sh, s3.sh) с следующими требованиями:
- Если скрипт не выводит ничего (stdout или stderr) в течение 1 минуты, он должен быть завершен
- После завершения следующий скрипт в последовательности должен запуститься автоматически
- Это должно продолжаться, пока все скрипты не будут обработаны
Текущая ситуация:
- Скрипты не завершаются сами, когда их задача выполнена
- В данный момент я вручную мониторю каждый скрипт и нажимаю Ctrl-c, когда замечаю, что нет вывода в течение некоторого времени
- Нужно автоматизировать это ручное вмешательство
Пример рабочего процесса:
- Запустить s1.sh
- Если s1.sh молчит 1 минуту → завершить его → запустить s2.sh
- Если s2.sh молчит 1 минуту → завершить его → запустить s3.sh
- …и так далее
Изучаемый подход:
Я думаю перенаправить как stdout, так и stderr в файл и проверять время изменения этого файла каждую секунду. Если файл не был изменен в течение 1 минуты, я могу предположить, что скрипт не выводит ничего и завершить его. Однако я не уверен, является ли этот подход жизнеспособным или существуют более лучшие решения.
Кто-нибудь реализовывал что-то подобное? Спасибо.
Точка начала может быть в использовании while read -t 60
для проверки, что command
выводит что-то за данное время. Теперь проблема в том, что нужно получить PID command
, когда хотите убить его. В следующем примере я обхожу это с помощью сигнала с ловушкой:
#!/bin/bash
trap 'kill %' USR1
for scr in s1.sh s2.sh s3.sh
do
"$scr" |& {
while read -r -N 1 -t 60
do
printf %s "$REPLY"
done
kill -USR1 "$$"
} &
wait
done
Ответ или решение
Решение задачи автоматического завершения оболочечных скриптов после 1 минуты отсутствия вывода требует аккуратного подхода и знания особенностей управления процессами в Linux. Ниже представлено детальное руководство, как автоматизировать этот процесс:
Задача: Автоматическое завершение скриптов оболочки
Цель: обеспечить последовательный запуск нескольких скриптов (s1.sh, s2.sh, s3.sh) таким образом, чтобы каждый следующий скрипт запускался только после завершения предыдущего. Если скрипт не выводит какие-либо данные в течение 1 минуты, он должен быть автоматически завершен.
Шаги решения
-
Расширение функционала скрипта с использованием subshell:
- Каждое выполнение скрипта должно проходить в контексте подшелла, чтобы отслеживать вывод и легко управлять процессом.
-
Использование команды
read
с таймаутом:- Пытаемся читать данные из потока вывода. Если данные не передаются в течение 60 секунд, запускается команда завершения процесса.
-
Обработка сигналов и управление процессами:
- Используем сигналы для аккуратного завершения процесса. Такой подход позволяет избежать утечек ресурсов и некорректного завершения скриптов.
Пример реализации
#!/bin/bash
# Функция для обработки сигнала завершения
trap 'kill %' USR1
# Массив скриптов для выполнения
scripts=("s1.sh" "s2.sh" "s3.sh")
for scr in "${scripts[@]}"
do
# Запускам скрипт как фоновый процесс и перенаправляем вывод
"$scr" |& {
while read -r -N 1 -t 60 # Чтение каждого байта с таймаутом в 60 секунд
do
printf "%s" "$REPLY" # Отображение текущего байта
done
kill -USR1 "$$" # Отправка сигнала на завершение
} &
wait # Ожидание завершения фонового процесса
done
Обоснование выбранного решения
- Параллелизм: Использование фоновых процессов и сигналов обеспечивает стабильное и последовательное выполнение без вмешательства пользователя.
- Контроль вывода: Чтение вывода в байтах позволяет точнее отслеживать активность скрипта.
- Обработка ошибок: Использование сигнала
USR1
гарантирует корректное завершение скрипта, даже если он оказался "повешен".
Особенности и ограничения
- Точность отслеживания: Этот подход способен точно мониторить активность вывода каждого скрипта.
- Затраты на ресурсы: Скрипты запускаются в отдельных процессах, что может незначительно увеличить потребление ресурсов системы.
- Универсальность: Подходит для большинства оболочек POSIX, но специфические системные команды могут потребовать модификации для других окружений (например, BSD).
В заключение, использование командных структур, таких как trap
и read
, в сочетании с фоновой обработкой вывода, позволяет автоматизировать ручное завершение скриптов. Это решение эффективно уменьшает человеческую ошибку, и обеспечивает надежность работы в разных системах, что делает его отличным выбором для автоматизации процессов в ИТ-среде.