Получение в скрипте bash PID процесса, запущенного в фоне.

Преамбула

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

openvpn --config ~/vpn/myvpn.ovpn &

Да, про опцию конфига daemon писать в комментах не надо, вызов openvpn просто для примера.

Но как же управлять процессом, например, остановить именно запущенный? По PID. Почему просто не воспользоваться pkill? Поясню на реальной задаче, например, на машине запускается несколько процессов openvpn, обеспечивающих коннект к нескольким провайдерам или нескольким сетям — если сделать pkill openvpn, положим сразу все процессы, а не конкретный. Значит, чтобы придушить конкретный процесс, надо получить конкретный PID.

Получение PID запущенного в фоне процесса.

На самом деле все придумали за нас, в bash есть системная переменная $!, хранящая PID последнего запущенного в фоне процесса.

Чтобы в другом скрипте остановить процесс, запущенный в первом, например, мы должны написать два скрипта для старта и остановки некоторой программы, мы должны куда-то сохранить полученный PID.

Демоны в Linux обычно делают текстовый файл (т.н. PID-файл), куда записывают свой PID при запуске. В своем скрипте мы можем сделать также:

openvpn --config ~/vpn/myvpn.ovpn & #запуск процесса
VPNPID=$! #сохраняем PID в переменную
echo "VPN PID $VPNPID" #выводим PID на консоль
echo $VPNPID > /tmp/myvpn.pid #сохраняем в файл

Использование сохраненного PID в другом скрипте

Например, для остановки процесса:

VPNPID=`cat "/tmp/myvpn.pid"` # Читаем PID-файл
echo "Stopping: $VPNPID" # Сообщение пользователю
kill "$VPNPID" # Завершаем процесс с сохраненным PID
rm "$PIDFILE" # Удаляем файл с неактуальным PID

Примечание по поводу network namespaces

Поскольку в системе всем процессам выдается уникальный PID, вне зависимости, например, от network namespace, в котором запущен процесс, соответственно, алгоритм сработает и для процесса, запущенного в сетевом неймспейсе:

Запуск:
ip netns exec <имя_неймспейса> openvpn --config ~/vpn/myvpn.ovpn &
VPNPID=$!
echo "VPN PID $VPNPID"
echo $VPNPID > /myfiles/server/ddns/vpn.pid

Останов:

VPNPID=`cat "/tmp/myvpn.pid"` # Читаем PID-файл
echo "Stopping: $VPNPID" # Сообщение пользователю
kill "$VPNPID" # Завершаем процесс с сохраненным PID
rm "$PIDFILE" # Удаляем файл с неактуальным PID

ФАНФАРЫ!

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *