Как проверить, работает ли данный PID?

Я пишу скрипт Perl, который анализирует лог-файлы для сбора PID, а затем проверяет, работает ли этот PID. Я пытаюсь думать о лучшем способе сделать эту проверку. Очевидно, я мог бы сделать что-то вроде:

system("ps $pid > /dev/null") && print "Not running\n"; 

Тем не менее, я бы предпочел избежать системного вызова, если это возможно. Поэтому я думал, что могу использовать файловую систему /proc (переносимость не вызывает беспокойства, это всегда будет работать в системе Linux). Например:

 if(! -d "/proc/$pid"){ print "Not running\n"; } 

Это безопасно? Могу ли я всегда утверждать, что если нет каталога /proc/$pid/ связанный PID не работает? Я ожидаю, так как AFAIK ps сам получает информацию из /proc но поскольку это для производственного кода, я хочу быть уверенным.

Итак, могут ли быть случаи, когда в запущенном процессе нет каталога /proc/PID или где существует каталог /proc/PID и процесс не запущен? Есть ли какая-то причина предпочитать парсинг ps над проверкой существования каталога?

Можно использовать функцию perl function kill(0,$pid) .

Если код возврата равен 1, тогда PID существует, и вам разрешено отправлять ему сигнал.

Если код возврата равен 0, вам нужно проверить $ !. Это может быть EPERM (разрешение отклонено), что означает, что процесс существует или ESRCH, в этом случае процесс не существует.

Если ваш проверочный код работает от имени root вы можете упростить это, просто проверив код возврата kill; 0 => ошибка, 1 => ok

Например:

 % perl -d -e 0 Loading DB routines from perl5db.pl version 1.37 Editor support available. Enter h or 'hh' for help, or 'man perldebug' for more help. main::(-e:1): 0 DB<1> print kill(0,500) 0 DB<2> print $! No such process DB<3> print kill(0,1) 0 DB<4> print $! Operation not permitted DB<5> print kill(0,$$) 1 

Это можно сделать простой функцией

 use Errno; sub test_pid($) { my ($pid)=@_; my $not_present=(!kill(0,$pid) && $! == Errno::ESRCH); return($not_present); } print "PID 500 not present\n" if test_pid(500); print "PID 1 not present\n" if test_pid(1); print "PID $$ not present\n" if test_pid($$); 
  • Я на 99.9% уверен, что проверка того, существует ли /proc/ PID (и является каталогом), на 98% надежнее, чем метод kill 0 . Причина, по которой 98% составляет не 100%, – это то, что Стивен Харрис коснулся (и отскочил) в комментарии, а именно, файловая система /proc не смогла быть смонтирована. Может быть справедливо утверждать, что система Linux без /proc является поврежденной, деградированной системой – в конце концов, такие вещи, как ps , top и lsof вероятно, не lsof – и это может быть не проблема для производственной системы. Но это (теоретически) возможно, что он никогда не был смонтирован (хотя это может помешать системе перейти в нормальное состояние), это определенно возможно для его размонтирования (я протестировал его 1 ), и я что нет никакой гарантии, что он будет существовать (т. е. POSIX не требуется). И, если система не будет полностью закрыта, kill будет работать.
  • Комментарий Стивена говорит о «выходе в файловую систему» ​​и «использовании собственных системных вызовов». Я считаю, что это в значительной степени красная селедка.
    • Да, любая попытка доступа /proc требует чтения корневого каталога для поиска файловой системы /proc . Это верно для любой попытки доступа к любому файлу по абсолютному пути, включая вещи в /bin , /etc и /dev . Это происходит так часто, что корневой каталог, безусловно, кэшируется в памяти на весь срок службы (время безотказной работы) системы, поэтому этот шаг можно выполнить без каких-либо дисковых операций ввода-вывода. И, как только у вас есть inode /proc , все остальное происходит в памяти.
    • Как вы /proc доступ /proc ? С stat , open , readdir и т. Д., readdir являются readdir системными вызовами, каждый бит, а также kill .
  • В этом вопросе речь идет о процессе. Это скользкая фраза. Если вы действительно хотите проверить, запущен ли процесс (т. Е. В очереди выполнения, может быть, текущий процесс на каком-то процессоре, а не в спящем, ожидающем или остановленном), вам может потребоваться выполнить ps PID и прочитать результат , или посмотрите /proc/ PID /stat . Но я не вижу намека на ваш вопрос или комментарии, что вы обеспокоены этим.

    Однако слон в комнате состоит в том, что процесс зомби 2 может быть трудно отличить от процесса, который жив и здоров. kill 0 работает на зомби, и /proc/ PID существует. Вы можете идентифицировать зомби с методами, перечисленными в предыдущем абзаце (делать ps PID и читать результат, или смотреть на /proc/ PID /stat ). Мое очень быстрое и случайное (то есть не очень тщательное) тестирование показывает, что вы также можете сделать это, выполнив readlink или lstat on /proc/ PID /cwd , /proc/ PID /root или /proc/ PID /exe – эти провалится на зомби. (Тем не менее, они также потерпят неудачу в процессах, которыми вы не владеете.)

____________
1, если параметр -f ( f orce) не работает, попробуйте -l ( l azy).
2, т. Е. Процесс, который вышел / умер / прекратился, но чей родитель еще не сделал wait .