[英]How to check if a process id (PID) exists
In a bash script, I want to do the following (in pseudo-code):在 bash 脚本中,我想执行以下操作(在伪代码中):
if [ a process exists with $PID ]; then
kill $PID
fi
What's the appropriate expression for the conditional statement?条件语句的适当表达式是什么?
The best way is:最好的办法是:
if ps -p $PID > /dev/null
then
echo "$PID is running"
# Do something knowing the pid exists, i.e. the process with $PID is running
fi
The problem with:问题在于:
kill -0 $PID
is the exit code will be non-zero even if the pid is running and you dont have permission to kill it.即使pid正在运行并且您无权杀死它,退出代码也将是非零的。 For example:例如:
kill -0 1
and和
kill -0 $non-running-pid
have an indistinguishable (non-zero) exit code for a normal user, but the init process (PID 1) is certainly running.对于普通用户,有一个无法区分的(非零)退出代码,但 init 进程(PID 1)肯定正在运行。
The answers discussing kill and race conditions are exactly right if the body of the test is a "kill".如果测试的主体是“kill”,那么讨论 kill 和 Race conditions 的答案是完全正确的。 I came looking for the general " how do you test for a PID existence in bash ".我来寻找一般的“你如何测试 bash 中的 PID 存在”。
The /proc method is interesting, but in some sense breaks the spirit of the "ps" command abstraction, ie you dont need to go looking in /proc because what if Linus decides to call the "exe" file something else? /proc 方法很有趣,但从某种意义上说,它打破了“ps”命令抽象的精神,也就是说,您不需要去查看 /proc,因为如果 Linus 决定将“exe”文件称为别的东西怎么办?
To check for the existence of a process, use要检查进程是否存在,请使用
kill -0 $pid
But just as @unwind said, if you're going to kill it anyway, just但正如@unwind 所说,如果你无论如何要杀死它,就
kill $pid
or you will have a race condition.否则你会遇到竞争条件。
If you want to ignore the text output of kill
and do something based on the exit code, you can如果你想忽略kill
的文本输出并根据退出代码做一些事情,你可以
if ! kill $pid > /dev/null 2>&1; then
echo "Could not send SIGTERM to process $pid" >&2
fi
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process exists"
fi
or或者
if [ -n "$(ps -p $PID -o pid=)" ]
In the latter form, -o pid=
is an output format to display only the process ID column with no header.在后一种形式中, -o pid=
是一种输出格式,仅显示没有标题的进程 ID 列。 The quotes are necessary for non-empty string operator -n
to give valid result.非空字符串运算符-n
需要引号才能给出有效结果。
ps
command with -p $PID
can do this:带有-p $PID
ps
命令可以执行此操作:
$ ps -p 3531
PID TTY TIME CMD
3531 ? 00:03:07 emacs
You have two ways:你有两种方法:
Lets start by looking for a specific application in my laptop:让我们首先在我的笔记本电脑中寻找一个特定的应用程序:
[root@pinky:~]# ps fax | grep mozilla
3358 ? S 0:00 \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2 S+ 0:00 \_ grep mozilla
All examples now will look for PID 3358.现在所有示例都将查找 PID 3358。
First way : Run "ps aux" and grep for the PID in the second column.第一种方法:在第二列中为 PID 运行“ps aux”和 grep。 In this example I look for firefox, and then for it's PID:在这个例子中,我寻找 firefox,然后寻找它的 PID:
[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358
So your code will be:所以你的代码将是:
if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
kill $PID
fi
Second way : Just look for something in the /proc/$PID
directory.第二种方式:只需在/proc/$PID
目录中查找内容即可。 I am using "exe" in this example, but you can use anything else.我在这个例子中使用了“exe”,但你可以使用其他任何东西。
[root@pinky:~]# ls -l /proc/3358/exe
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash
So your code will be:所以你的代码将是:
if [ -f /proc/$PID/exe ]; then
kill $PID
fi
BTW: whats wrong with kill -9 $PID || true
顺便说一句: kill -9 $PID || true
有什么问题kill -9 $PID || true
kill -9 $PID || true
? kill -9 $PID || true
吗?
EDIT:编辑:
After thinking about it for a few months.. (about 24...) the original idea I gave here is a nice hack, but highly unportable.在考虑了几个月之后......(大约 24 ......)我在这里给出的最初想法是一个很好的黑客,但非常不可移植。 While it teaches a few implementation details of Linux, it will fail to work on Mac, Solaris or *BSD.虽然它讲授了 Linux 的一些实现细节,但它无法在 Mac、Solaris 或 *BSD 上运行。 It may even fail on future Linux kernels.它甚至可能在未来的 Linux 内核上失败。 Please - use "ps" as described in other responses.请 - 使用“ps”,如其他回复中所述。
It seems like you want好像你想要
wait $PID
which will return when $pid
finishes.这将在$pid
完成时返回。
Otherwise you can use否则你可以使用
ps -p $PID
to check if the process is still alive (this is more effective than kill -0 $pid
because it will work even if you don't own the pid).检查进程是否还活着(这比kill -0 $pid
更有效,因为即使您不拥有 pid 它也能工作)。
I think that is a bad solution, that opens up for race conditions.我认为这是一个糟糕的解决方案,它为竞争条件开辟了道路。 What if the process dies between your test and your call to kill?如果进程在您的测试和您的 kill 调用之间终止了怎么办? Then kill will fail.那么kill就会失败。 So why not just try the kill in all cases, and check its return value to find out how it went?那么为什么不在所有情况下都尝试 kill 并检查其返回值以了解它是如何进行的呢?
code below checks if my process is running, if so do nothing. 下面的代码检查我的进程是否正在运行,如果是,则不执行任
let's check new messages from Amazon SQS every hour only and only if the process is not running. 让我们每小时检查来自Amazon SQS的新消息,并且仅在进程未运行时才检查。
#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
/usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
echo "do nothing, just smile =)"
fi
exit $?
By pid :通过pid :
pgrep [pid] >/dev/null
By name :按名称:
pgrep -u [user] -x [name] >/dev/null
" -x " means "exact match". “ -x ”表示“完全匹配”。
For example in GNU/Linux you can use:例如在 GNU/Linux 中,您可以使用:
Pid=$(pidof `process_name`)
if [ $Pid > 0 ]; then
do something
else
do something
fi
Or something like或者类似的东西
Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN
and that shows you the name of the app, just the name without ID.这会显示应用程序的名称,只是没有 ID 的名称。
here i store the PID in a file called .pid (which is kind of like /run/...) and only execute the script if not already being executed.在这里,我将 PID 存储在一个名为 .pid 的文件中(类似于 /run/...),并且仅在尚未执行的情况下才执行脚本。
#!/bin/bash
if [ -f .pid ]; then
read pid < .pid
echo $pid
ps -p $pid > /dev/null
r=$?
if [ $r -eq 0 ]; then
echo "$pid is currently running, not executing $0 twice, exiting now..."
exit 1
fi
fi
echo $$ > .pid
# do things here
rm .pid
note: there is a race condition as it does not check how that pid is called.注意:存在竞争条件,因为它不检查该 pid 的调用方式。 if the system is rebooted and .pid exists but is used by a different application this might lead 'unforeseen consequences'.如果系统重新启动并且 .pid 存在但被不同的应用程序使用,这可能会导致“不可预见的后果”。
This answer has been rewritten since the downvote.自反对票以来,此答案已被重写。
I learned from and upvoted @FDS's answer here , because it is good and correct.我从@FDS's answer here 中学习并投票赞成,因为它很好而且正确。 But, here's a form I find easier to read and understand.但是,这是一个我觉得更容易阅读和理解的表格。
Explanation:解释:
"$?"
"$?"
part means "the exit or return code from the previous command". part 表示“上一个命令的退出或返回代码”。ps --pid "$pid"
command returns exit code 0
if the specified PID ( "$pid"
) is running, and some other number if not.如果指定的 PID ( "$pid"
) 正在运行,则ps --pid "$pid"
命令返回退出代码0
,否则返回其他数字。> /dev/null
discards all output printed to stdout
, since we don't want to see it.执行> /dev/null
会丢弃打印到stdout
的所有输出,因为我们不想看到它。 Rather, all we want is the exit code ( "$?"
) from the ps --pid "$pid"
command to see if that PID is running.相反,我们想要的只是ps --pid "$pid"
命令的退出代码 ( "$?"
),以查看该 PID 是否正在运行。 More specifically, using > /dev/null
redirects stdout
output to the /dev/null
pseudofile, whose purpose is to discard all incoming input.更具体地说,使用> /dev/null
将stdout
输出重定向到/dev/null
伪文件,其目的是丢弃所有传入的输入。pid=1234
ps --pid "$pid" > /dev/null
if [ "$?" -eq 0 ]; then
echo "PID $pid exists and is running."
fi
Running shellcheck path/to/this_script.sh
tells me I should actually do it the other way (as @FDS shows) to avoid redundancy.运行shellcheck path/to/this_script.sh
告诉我实际上应该以另一种方式(如@FDS 所示)来避免冗余。 See the shellcheck
output here:在此处查看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...
Notice especially this part:特别注意这部分:
SC2181: Check exit code directly with eg '
if mycmd;
SC2181:直接使用例如'if mycmd;
', not indirectly with$?
',不是间接用$?
. .
See the full description for this error code here: https://github.com/koalaman/shellcheck/wiki/SC2181 .在此处查看此错误代码的完整描述: https ://github.com/koalaman/shellcheck/wiki/SC2181。
shellcheck
recommends this form instead:所以, shellcheck
推荐这种形式:pid=1234
if ps --pid "$pid" > /dev/null; then
echo "PID $pid exists and is running."
fi
If you want to adjust to doing it that way, go for it.如果你想适应那样做,那就去做吧。 But, if you'd rather do it my way because you consider my way easier to read and understand, as I do, then you can optionally disable that shellcheck
warning by adding # shellcheck disable=SC2181
above that line, like this:但是,如果你宁愿按照我的方式做,因为你认为我的方式更容易阅读和理解,就像我一样,那么你可以选择通过在该行上方添加# 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
The key takeaway here, however, is to never insert any command, not even an echo
or print
statement, between the command being checked ( ps
in this case) and checking the error code with "$?"
然而,这里的关键点是永远不要在被检查的命令(在这种情况下为ps
)和用"$?"
检查错误代码之间插入任何命令,甚至是echo
显或print
语句。 , or else checking the error code will accidentally check the error code from the latest command, such as the inserted echo
or print
statement , instead of from the command of interest ( ps
in our case)! , 否则检查错误代码会意外地从最新命令中检查错误代码,例如插入的echo
或print
语句,而不是从感兴趣的命令(在我们的例子中为ps
)!
That's the main reason shellcheck
recommends what they do: they want to make sure you're checking the error code of the correct command.这就是shellcheck
推荐他们做什么的主要原因:他们想确保您检查的是正确命令的错误代码。
Other than that, it's just a pedantic opinion-based-discussion-equivalent to the argument in C about how you should check for NULL
(null pointer) values:除此之外,它只是一个迂腐的基于意见的讨论,相当于 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.
So, just as which way you choose to check for NULL
values (null ptrs) in C is purely a matter of taste, which way in bash you choose to check for error codes/return codes is also purely a matter of taste.因此,正如您选择在 C 中选择哪种方式检查NULL
值(null ptrs)纯粹是个人喜好问题一样,在 bash 中选择哪种方式检查错误代码/返回代码也纯粹是个人喜好问题。 Currently, I prefer the version above I have marked as "My final and preferred answer".目前,我更喜欢上面我标记为“我的最终和首选答案”的版本。
check_if_pid_exists.sh from my eRCaGuy_hello_world repo: 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
Sample run calls and output:示例运行调用和输出:
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.
You can find valid PIDs (Process IDs) to send to my script by first running ps aux
and choosing a PID to pass to it.您可以通过首先运行ps aux
并选择要传递给它的 PID 来找到要发送到我的脚本的有效 PID(进程 ID)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.