Сценарий Bash, чтобы сигнализировать одновременно исполняемый экземпляр (тот же скрипт) о состоянии и счетчике приращения

Задний план

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

Однако, поскольку это запланированное задание, сценарий будет выполняться снова и снова и снова. В реальном сценарии, который у меня есть, файл отслеживает количество сбоев. Когда он достигает порога, почта отправляется администратору, если исходный сценарий становится зомби или иным образом застревает. Если порог достигнут, и начальный процесс, который утверждает, что блокировка больше не живет, блокировка прерывается, и альтернативный текст отправляется администратору, информируя об этом состоянии. Все это, вероятно, не очень актуально для проблемы, но я хочу дать полную картину здесь.

Всякий раз, когда достигается порог, счетчик сбоев в файле сбрасывается и начинается оттуда. Таким образом, исходный экземпляр может или не сможет увидеть файл счетчика сбоев.

Исходный экземпляр скрипта, который удерживал блокировку, (надеюсь) закончит свою работу и завершит работу.

Вопрос

Как я могу реализовать схему, в которой «неудачные» экземпляры, которые сталкиваются с блокировкой, посылают сигнал (я пробовал SIGUSR1 ) исходному экземпляру, а исходный экземпляр отслеживает, сколько раз он «пинговал»?

Вот тестовый сценарий, который я придумал до сих пор:

 #!/usr/bin/env bash LOCKFILE=/tmp/$(basename $0).lock let COUNTER=0 function concurrent_run { let COUNTER=COUNTER+1 echo -e "\ncaught SIGUSR1 (counter = $COUNTER)" } if ( set -o noclobber; echo "$$" > "$LOCKFILE" ) 2> /dev/null; then trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT trap concurrent_run USR1 echo "I was first, going to sleep" sleep 100000 trap - INT TERM EXIT USR1 else LOCKPID=$(cat "$LOCKFILE") echo "Lock already held by $LOCKPID" [[ -n "$LOCKPID" ]] && kill -0 $LOCKPID && { kill -USR1 $LOCKPID; echo "... knock knock? ($LOCKPID)"; } exit 1 fi echo "End: $COUNTER" exit 0 

( sleep имитирует длительную работу, выполняемую реальным скриптом)

Я тестирую Linux, и я пробовал имя для сигнала как USR1 и SIGUSR1 , оба дают тот же результат (т. Е. Нет).

 builtin trap -l 

дал мне 10 как SIGUSR1 , поэтому я также попробовал ручную kill -10 PID на PID исходного экземпляра. К сожалению, я не могу заставить его видеть сигнал.

Что я делаю не так?


Как протестировать

Начните один экземпляр скрипта (я назвал его sigtest ):

 $ ./sigtest I was first, going to sleep 

Запустите второй экземпляр скрипта в другом терминале, окне, панели (тот же пользователь!):

 $ ./sigtest Lock already held by 15360 ... knock knock? (15360) 

Повторение …

Ожидаемый результат в первом терминале (пропуская пустые строки):

 caught SIGUSR1 (counter = 1) caught SIGUSR1 (counter = 2) caught SIGUSR1 (counter = 3) caught SIGUSR1 (counter = 4) 

Версия Bash

 $ echo $BASH_VERSION 4.1.5(1)-release 

  • Почему командный игрок снова начинается после того, как его убили
  • убивать или удалять всех клиентов из работающего vncserver без перезапуска сервера
  • Есть ли способ сказать, был ли сценарий оболочки убит сигналом 9
  • Как убить два или несколько процессов с помощью одной команды kill?
  • Завершить каждый фоновый процесс
  • Идентификатор процесса печати (PID) экземпляра Matlab
  • Как закрыть сеанс XServer с помощью команды
  • Как правильно остановить процесс оболочки busybox и дочерний процесс?
  • 2 Solutions collect form web for “Сценарий Bash, чтобы сигнализировать одновременно исполняемый экземпляр (тот же скрипт) о состоянии и счетчике приращения”

    человек bash:

    Если bash ожидает завершения команды и получает сигнал, для которого установлена ​​ловушка, ловушка не будет выполняться до тех пор, пока команда не завершится. Когда bash ожидает асинхронную команду через встроенный wait, прием сигнала, для которого была установлен ловушка, заставит wait builtin немедленно возвращаться с статусом выхода более 128, сразу после которого выполняется ловушка.

    Заставьте его sleep 100 и дождитесь его завершения. Однако я не знаю, обрабатываются ли несколько сигналов несколько раз.

    Вы можете сообщить счетчик в долгосрочную работу двумя основными способами:

    1. Общий счетчик, защищенный второй блокировкой; или
    2. Коллекция неразделенных счетчиков, которые агрегируются по длительной работе.

    Общий счетчик достаточно прост:

     if (set -o noclobber; echo $$ > /tmp/grumpy-waiters.lock); then echo >> /tmp/grumpy-waiters rm -f /tmp/grumpy-waiters.lock fi 

    Долгосрочная работа может затем прочитать счетчик следующим образом:

     num_grumpy_waiters=0 if [ -s /tmp/grumpy-waiters ]; then num_grumpy_waiters=$(wc -c < /tmp/grumpy-waiters) fi 

    Подход с нечеткой коллекцией включает создание нескольких файлов без необходимости блокировки. Это менее рискованно, но более тщательно. Каждый неудачный экземпляр создает или обновляет свой собственный счетчик:

     grumpy_shard=1 if [ -s /tmp/grumpy.${LOCKPID}.$$ ]; then grumpy_shard=$(expr $(cat /tmp/grumpy.${LOCKPID}.$$) + 1) fi echo ${grumpy_shard} > /tmp/grumpy.${LOCKPID}.$$ 

    Длительный экземпляр может подбирать эти счетчики и группировать их сразу же после освобождения главного замка:

     num_grumpy_waiters=$(cat /tmp/grumpy.$$.* 2>/dev/null | awk 'BEGIN{s=0}NF>0{s=s+int($1)}END{print s}') rm -f /tmp/grumpy.$$.* 2>/dev/null 

    В любом случае использование сигналов для прерывания сценария оболочки не приведет к своевременному прерыванию. Если вам это нужно, сценарий должен разблокировать слушателя на свой собственный фон, чтобы он мог сразу реагировать на сигнал.

    Interesting Posts

    Есть ли простой способ создать скрипт FreeBSD rc?

    aptitude search не видит deb, но он существует в репо: http://http.kali.org/pool/main/s/simplejson/

    Как я могу запускать две команды параллельно и завершать их, если ОДИН из них завершается с кодом выхода 0?

    Как получить общее количество строк и уникальных счетчиков в одной строке

    Как определить, использует ли текущий язык кодировку UTF-8?

    Как получить точку монтирования файловой системы, содержащую данный файл

    Как создать ярлык для рабочего стола KDE для Firefox?

    Как выполнить двойную загрузку Ubuntu и Phoenix OS

    После каждого обновления ядра опция отладки является первой в списке при загрузке

    Как стереть или записать нули на жесткий диск с помощью / dev / sg2

    У экземпляра Debian два ядра после установки драйверов Intel PCIe SSD – один с черным экраном

    Как связать разные (несовместимые) библиотеки во время выполнения в зависимости от программы?

    Bash для чтения двух конкретных строк из текстового файла и использования частей из них в качестве переменной

    Что противоположно «grep»?

    Как я могу отключить автозапуск lightdm из командной строки, когда невозможно получить сеанс GUI?

    Linux и Unix - лучшая ОС в мире.