如何检查进程ID(PID)是否存在

246

在Bash脚本中,我想要执行以下操作(伪代码):

if [ a process exists with $PID ]; then

    kill $PID 

fi

条件语句的适当表达式是什么?


1
通过 路径:https://dev59.com/-4nca4cB1Zd3GeqP5xJz - Alberto Salvia Novella
2
按名称:https://askubuntu.com/questions/157779/how-to-determine-whether-a-process-is-running-or-not-and-make-use-it-to-make-a-c/1317605 - Alberto Salvia Novella
11个回答

0

从这里学到并点赞了 @FDS 的答案, 因为它很好也是正确的。但是,这里有个我认为更容易阅读和理解的表格。

所以,这是我的首选版本:

说明:

  1. "$?" 部分表示“前一个命令的退出或返回代码”。
  2. ps --pid "$pid" 命令返回退出代码 0,如果指定的 PID("$pid")正在运行,则返回其他数字。
  3. 使用 > /dev/null 可以丢弃所有打印到 stdout 的输出,因为我们不想看到它们。相反,我们只需要来自 ps --pid "$pid" 命令的退出代码("$?")来查看该 PID 是否正在运行。更具体地说,使用 > /dev/nullstdout 输出重定向到虚拟文件 /dev/null 中,其目的是丢弃所有传入输入。
pid=1234
ps --pid "$pid" > /dev/null
if [ "$?" -eq 0 ]; then
    echo "PID $pid exists and is running."
fi

运行 shellcheck path/to/this_script.sh 告诉我应该按照 @FDS 的方式来避免冗余。在这里查看 shellcheck 输出:

eRCaGuy_hello_world/bash$ shellcheck check_if_pid_exists.sh 

In check_if_pid_exists.sh line 46:
if [ "$?" -eq 0 ]; then
     ^--^ SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

For more information:
  https://www.shellcheck.net/wiki/SC2181 -- Check exit code directly with e.g...

特别注意这部分:

SC2181:直接使用 'if mycmd;' 检查退出代码,而不是间接使用 $?

在此处查看此错误代码的完整描述:https://github.com/koalaman/shellcheck/wiki/SC2181

因此,shellcheck 建议使用以下形式:

pid=1234
if ps --pid "$pid" > /dev/null; then
    echo "PID $pid exists and is running."
fi

如果你想调整成那种方式,就去试试吧。但是,如果你认为我的方式更易于阅读和理解,像我一样,那么你可以通过在那行上面添加# shellcheck disable=SC2181来选择性地禁用shellcheck警告,就像这样:

我的最终和首选答案

ps --pid "$pid" >/dev/null
# shellcheck disable=SC2181
if [ "$?" -eq 0 ]; then
    echo "PID $pid exists and is running."
else
    echo "PID $pid does NOT exist."
fi

然而,这里的关键是永远不要在正在检查的命令(在本例中为ps)和使用"$?"检查错误代码之间插入任何命令,甚至不是echoprint语句,否则检查错误代码将意外地检查最新命令的错误代码,例如插入的echoprint语句,而不是感兴趣的命令(在我们的例子中为ps)!

这就是为什么shellcheck建议他们所做的事情的主要原因:他们想确保您检查了正确命令的错误代码。

除此之外,这只是一个吹毛求疵的基于观点的讨论,相当于C语言中关于如何检查NULL(空指针)值的争论:

// The way preferred by pedantic people who don't want to "be redundant" with 
// an "unnecessary" `== NULL` check:
if (!some_ptr)
{
    printf("ERROR: null ptr.\n");
    return;
}

// Versus the more-readable and understandable way which I prefer to use
// whenever my peers will approve it without a fight or long argument
if (some_ptr == NULL)       // in C
// if (some_ptr == nullptr) // in C++
{
    printf("ERROR: null ptr.\n");
    return;
}

// Note: I just want to get my code merged and move on with life, so if they
// won't easily approve my preferred version above, I'll switch to the other,
// more-pedantic version of code to try to get a quick approval so I can be
// more productive. 
// There are few things more discouraging than being blocked over
// silly "pedantry" when your code is correct, bug-free, well-written, and does
// what it says it does.

因此,就像在C语言中选择检查NULL值(空指针)的方式一样,检查bash中的错误代码/返回代码的方式也纯粹是品味问题。目前,我更喜欢上面标记为“我的最终和首选答案”的版本。

无论如何,这里有一个完整可运行的程序

check_if_pid_exists.sh 来自我的eRCaGuy_hello_world仓库:

#!/usr/bin/env bash

pid=1234

if [ "$#" -gt 0 ]; then
    # At least 1 argument was passed in, so assume it is the PID
    pid="$1"
fi

# Try to print the process (`ps`) information for this PID. Send it to
# /dev/null, however, so we don't actually have to look at it. We just want
# the return code, `$?`, which will be 0 if the process exists and some other
# number if not.
ps --pid "$pid" > /dev/null
# shellcheck disable=SC2181
if [ "$?" -eq 0 ]; then
    echo "PID $pid exists and is running."
else
    echo "PID $pid does NOT exist."
fi

示例运行调用和输出:

eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh 28876
PID 28876 exists and is running.

eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh
PID 1234 does NOT exist.

eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh 5678
PID 5678 does NOT exist.

您可以通过先运行ps aux并选择要传递给我的脚本的PID来找到有效的PID(进程ID)。

相关

  1. 我在如何在bash中等待多个子进程完成,并在任何子进程以代码!=0结束时返回exit code !=0?上的答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接