Как автоматически завершать выполнение сценариев оболочки после 1 минуты отсутствия вывода

Вопрос или проблема

Мне нужно запустить несколько shell-скриптов последовательно (s1.sh, s2.sh, s3.sh) с следующими требованиями:

  • Если скрипт не выводит ничего (stdout или stderr) в течение 1 минуты, он должен быть завершен
  • После завершения следующий скрипт в последовательности должен запуститься автоматически
  • Это должно продолжаться, пока все скрипты не будут обработаны

Текущая ситуация:

  • Скрипты не завершаются сами, когда их задача выполнена
  • В данный момент я вручную мониторю каждый скрипт и нажимаю Ctrl-c, когда замечаю, что нет вывода в течение некоторого времени
  • Нужно автоматизировать это ручное вмешательство

Пример рабочего процесса:

  1. Запустить s1.sh
  2. Если s1.sh молчит 1 минуту → завершить его → запустить s2.sh
  3. Если s2.sh молчит 1 минуту → завершить его → запустить s3.sh
  4. …и так далее

Изучаемый подход:
Я думаю перенаправить как 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 минуты, он должен быть автоматически завершен.

Шаги решения

  1. Расширение функционала скрипта с использованием subshell:

    • Каждое выполнение скрипта должно проходить в контексте подшелла, чтобы отслеживать вывод и легко управлять процессом.
  2. Использование команды read с таймаутом:

    • Пытаемся читать данные из потока вывода. Если данные не передаются в течение 60 секунд, запускается команда завершения процесса.
  3. Обработка сигналов и управление процессами:

    • Используем сигналы для аккуратного завершения процесса. Такой подход позволяет избежать утечек ресурсов и некорректного завершения скриптов.

Пример реализации

#!/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, в сочетании с фоновой обработкой вывода, позволяет автоматизировать ручное завершение скриптов. Это решение эффективно уменьшает человеческую ошибку, и обеспечивает надежность работы в разных системах, что делает его отличным выбором для автоматизации процессов в ИТ-среде.

Оцените материал
Добавить комментарий

Капча загружается...