В моих сценариях запуска linux, когда я запускаю такой процесс, как (в этом примере используется openvpn, но вопрос является общим для любого процесса);
openvpn --config /etc/myserver.conf
как лучше всего найти его и быть на 100% уверенным, что это правильный процесс, и убить его в разделе остановки? Обычно я использую такие вещи, как:
pid=$(ps -efww | grep -v grep | grep openvpn | grep /etc/myserver.conf | awk '{print $2}')
Конечно, он работает почти всегда, но иногда возникают проблемы со случайным сопоставлением процессов с почти одинаковым именем (например, myserver.conf-new), поэтому я ищу лучший подход.
ps e -ef | grep MYID=myserver
? Тем не менее может возникнуть та же проблема со случайным соответствием.Хотелось бы, чтобы было что-нибудь легкое вроде:
launch --tag myserver openvpn --config /etc/myserver.conf
и
pgrep --tag myserver
Спасибо @Iain, @KyleSmith и @ M_1 за ваши ответы и за то, что помогли мне начать работу над Server Fault. Если бы у меня здесь было больше репутации, я бы поставил +1 вам, ребята. (Изменить: теперь у меня есть репутация, +1 все вокруг).
Я собираюсь ответить на свой вопрос, потому что я нашел то, что делает то, что искал: общее решение, которое позволяет избежать неточного сопоставления с шаблоном с помощью ps и не использует файлы pid. Совершенно субъективно, что это был бы «лучший» способ, потому что, очевидно, существует долгая и успешная история использования файлов pid в unix, однако я явно сказал, что это было то, что мне не нравилось по разным причинам, а именно: они могут быть сложно создать должным образом, отличается для каждого программного обеспечения, выполняется по-разному в каждом дистрибутиве, может быть устаревшим / перезаписанным и по своей сути не обязательно отражает то, что на самом деле происходит. Я лучше использую какие-то теги процессов, спрашиваю ядро и получаю реальные ответы.
Урезанный пример:
#!/bin/sh
_TAG=d726cc7fa57a308afdc057b228a13f6d
case "$1" in
start)
_TAG=$_TAG ./self-backgrounding-process
_TAG=$_TAG ./non-self-backgrounding-process &
;;
stop)
pids=$(grep -l "\b_TAG=$_TAG\b" /proc/*/environ | cut -d/ -f3)
[ -n "$pids" ] && kill $pids
;;
esac
Ключевые моменты:
Я не уверен, что мне нравится загрязнять окружающую среду, но я не знаю другого способа (например, в проектах Solaris) пометить процесс Linux произвольным образом, чтобы я мог позже попросить ядро. По крайней мере, / proc / <pid> / Environment кажется отражать среду при запуске и не подвергаться никаким изменениям, которые процесс может внести после, что предполагает, что это должно быть надежно, однако есть вероятность, что это может измениться неожиданно. Это может работать или не работать вне Linux, в зависимости от реализации / proc и grep в ОС.
Думаю, я попробую на время и посмотрю, как пойдет.
Не бойтесь pid-файлов, они проверены и правдивы и обычно принадлежат root! :)
Большинство дистрибутивов используют стандартную функцию или двоичный файл для запуска демонов и сохранения результирующего PID в файле. В Debian, например, у вас есть start-stop-daemon с --pidfile
вариант. В других дистрибутивах есть /etc/rc.d/init.d/functions
(или аналогичные), которые используются для запуска демонов. Ознакомьтесь с некоторыми из наиболее общих сценариев запуска, включенных в ваш дистрибутив.
Хорошей идеей было бы использовать простой сценарий оболочки bash, который записывает файл блокировки / pid этого приложения (обычно используется на веб-серверах или базах данных), а затем использует этот файл, чтобы убить именно этот процесс, если это необходимо.
В частности, для openvpn вы можете использовать --writepid /path/to/file
параметр командной строки, например
/usr/sbin/openvpn --writepid /var/run/openvpn/server.pid --config /etc/myserver.conf ...
Это запишет PID основного процесса openvpn в указанный файл.
В общем, вы можете заключить свою программу в небольшой скрипт и использовать bash $!
встроенная переменная для записи pid в файл
#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file