October 3

Linux: как заставить скрипты перечитывать конфигурацию во время работы

Подписывайтесь на телеграм-канал usr_bin, где я публикую много полезного по Linux, в том числе ссылки на статьи в этом блоге.

Предположим, следующий сценарий: вы создаете скрипт, обрабатывающий файлы. Ваш скрипт уже наполовину обработал 1 000 000 файлов. Но вам нужно внести небольшое изменение: задать интервал ожидания между обработкой файлов. Хотя это незначительное изменение, не хотелось бы останавливать столь трудоемкую задачу обработки файлов, которая уже выполнена наполовину. Что ж! Есть способ, и он очень простой!

Давайте сначала поговорим о сигналах

В Linux (и других операционных системах семейства Unix) сигналы — это способ информирования процесса о конкретном событии. Это программные прерывания, которые операционная система отправляет процессу, чтобы указать, что определенное событие или условие требует внимания.

Некоторые очень распространенные сигналы, которые вы, вероятно, использовали:

  • SIGINT: ctrl+c прерывание запущенного процесса с клавиатуры.
  • SIGKILL: немедленно завершает процесс, не может быть перехвачен, заблокирован или проигнорирован, kill -9 <PID>
  • SIGHUP: Часто используется для указания процессу, что необходимо перечитать свою конфигурацию, kill -HUP <PID>

SIGHUP — это сигнал, который будем использовать ниже!

Сценарий!

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

Сохраните файл как config.cfg

sleep_value=2

Сохраните файл как myscript.sh

#!/bin/bash

read_config() {
    echo "Reading configuration."
    source ./config.cfg
}

trap 'read_config' SIGHUP

read_config

counter=0
while true; do
    counter=$((counter+1))
    echo "Processing file ${counter} .."
    echo "Sleeping for ${sleep_value} seconds."
    sleep $sleep_value
done

Предоставьте скрипту права на выполнение с помощью команды chmod

chmod +x ./myscript.sh

Тестирование сценария

Запуск скрипта даст такой вывод

Reading configuration.
Processing file 1 ..
Sleeping for 2 seconds.
Processing file 2 ..
Sleeping for 2 seconds.
Processing file 3 ..
Sleeping for 2 seconds.
Processing file 4 ..

Теперь из другого окна терминала, не прерывая процесс, измените config.cfg файл sleep_value=10

sleep_value=10

Сохраните файл и в том же терминале найдите PID скрипта с помощью следующей команды:

ps aux | grep -i myscript.sh | grep -v grep | tr -s " " | cut -d " " -f2
2544

Теперь попросим процесс перечитать его конфигурацию.

kill -HUP 2544

Теперь вернемся к терминалу запущенного скрипта. Мы можем заметить две вещи:

  • Интервал ожидания теперь стал равным 10.
  • Счетчик обработанных файлов не сбрасывается, а продолжает увеличиваться с момента перезагрузки.
Processing file 121 ..
Sleeping for 2 seconds.
Processing file 122 ..
Sleeping for 2 seconds.
Reading configuration.
Processing file 123 ..
Sleeping for 10 seconds.
Processing file 124 ..
Sleeping for 10 seconds.
Processing file 125 ..

В чем магия

Вся эта магия в скрипте происходит из-за команды trap, которая настроена на выполнение определенной функции при возникновении определенного сигнала. В нашем случае мы настроили ее на выполнение функции read_config в случае SIGHUP (сигнал, который указывает процессу перечитать свою конфигурацию).

trap 'read_config' SIGHUP

Функция read_config очень проста, она просто просит bash использовать ее sourceдля загрузки переменных из файла config.cfg. Обратите внимание, что source не ограничивается только переменными, но может также использоваться для загрузки функций и предоставления им доступа к основному скрипту.

source ./config.cfg

На этом все! Спасибо за внимание! Если статья была интересна, подпишитесь на телеграм-канал usr_bin, где будет еще больше полезной информации.