Linux: как заставить скрипты перечитывать конфигурацию во время работы
Подписывайтесь на телеграм-канал usr_bin, где я публикую много полезного по Linux, в том числе ссылки на статьи в этом блоге.
Предположим, следующий сценарий: вы создаете скрипт, обрабатывающий файлы. Ваш скрипт уже наполовину обработал 1 000 000 файлов. Но вам нужно внести небольшое изменение: задать интервал ожидания между обработкой файлов. Хотя это незначительное изменение, не хотелось бы останавливать столь трудоемкую задачу обработки файлов, которая уже выполнена наполовину. Что ж! Есть способ, и он очень простой!
Давайте сначала поговорим о сигналах
В Linux (и других операционных системах семейства Unix) сигналы — это способ информирования процесса о конкретном событии. Это программные прерывания, которые операционная система отправляет процессу, чтобы указать, что определенное событие или условие требует внимания.
Некоторые очень распространенные сигналы, которые вы, вероятно, использовали:
- SIGINT:
ctrl+c
прерывание запущенного процесса с клавиатуры. - SIGKILL: немедленно завершает процесс, не может быть перехвачен, заблокирован или проигнорирован,
kill -9 <PID>
- SIGHUP: Часто используется для указания процессу, что необходимо перечитать свою конфигурацию,
kill -HUP <PID>
SIGHUP — это сигнал, который будем использовать ниже!
Сценарий!
В примере ниже создадим скрипт и файл конфигурации. Скрипт будет считывать свой файл конфигурации при запуске, и вы увидите, что нужно добавить в скрипт, чтобы повторно загрузить конфигурацию во время работы, не прерывая выполнение скрипта.
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, где будет еще больше полезной информации.