我应该如何检查给定的PID是否正在运行?

我应该如何检查给定的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 不会运行?我希望如此,因为 AFAIKps本身无论如何都会获取其信息/proc,但由于这是用于生产代码,所以我想确定一下。

那么,是否存在正在运行的进程没有/proc/PID目录或/proc/PID存在目录但进程未运行的情况?是否有任何理由更喜欢解析ps而不是检查目录是否存在?

答案1

kill(0,$pid)可以使用perl函数。

如果返回码为 1,则 PID 存在,您可以向其发送信号。

如果返回码是0那么你需要检查$!。它可能是 EPERM(权限被拒绝),这意味着进程存在,或者是 ESRCH,在这种情况下进程不存在。

如果您的检查代码正在运行,root那么您可以将其简化为仅检查kill的返回代码; 0=> 错误,1=> 正常

例如:

% perl -d -e 0

Loading DB routines from perl5db.pl version 1.37
Editor support available.

Enter h or 'h h' 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($$);

答案2

  • 我 99.9% 确信检查是否存在(并且是一个目录)与该技术一样可靠 98% 。 98% 不是 100% 的原因是史蒂芬·哈里斯 (Stephen Harris) 谈到(并反驳)的一点/proc/PIDkill 0在评论中— 即,/proc文件系统可能未安装。声称没有的 Linux 系统/proc 是一个损坏的、降级的系统可能是有效的 — 毕竟,诸如pstop、 和 之类的东西lsof可能无法工作 — 因此这对于生产系统来说可能不是问题。但(理论上)它有可能永远不会被安装(尽管这可能会阻止系统进入正常状态),它绝对有可能被卸载(我已经测试过1),并且我相信没有任何保证它会存在(即 POSIX 不要求它)。而且,除非系统完全被冲洗,否则kill它将起作用。
  • 斯蒂芬的评论谈到了“进入文件系统”和“使用本机系统调用”。我认为这很大程度上是转移注意力。
    • 是的,任何访问尝试都/proc 需要读取根目录寻找文件/proc系统。对于任何访问尝试都是如此任何文件的绝对路径名,包括/bin/etc和中的内容/dev。这种情况经常发生,以至于根目录肯定会在系统的整个生命周期(正常运行时间)内缓存在内存中,因此这一步可以在没有任何磁盘 I/O 的情况下完成。而且,一旦有了 的索引节点/proc,发生的所有其他事情都在内存中。
    • 你如何访问/procstatopenreaddir等,它们都是本机系统调用,与kill.
  • 该问题讨论的是一个正在运行的进程。这是一个狡猾的短语。如果你真的想测试这个过程是否是跑步 (即,在运行队列中;可能是某个 CPU 上的当前进程;没有休眠、等待或停止),您可能需要执行ps PID 并读取输出,或者看看。但我在你的问题或评论中没有看到任何迹象表明你对此感到担忧。/proc/PID/stat

    然而,房间里的大象是僵尸2进程可能很难与正常运行的进程区分开来。  kill 0对僵尸起作用并且存在。您可以使用上一段中列出的技术(执行并读取输出,或查看)来识别僵尸。我非常快速和随意(即不是很彻底)的测试表明,您也可以通过执行 a或 on 、、 or来做到这一点 - 这些在僵尸上会失败。 (但是,它们也会在不属于您的进程上失败。)/proc/PIDps PID/proc/PID/statreadlinklstat/proc/PID/cwd/proc/PID/root/proc/PID/exe

____________
1 如果-f(Force) 选项不起作用,请尝试-l(阿兹)。
2 即,一个进程已退出/死亡/终止,但其父进程尚未执行wait.

相关内容