如何获取后台进程的进程ID?
我从 shell 脚本启动一个后台进程,我想在脚本完成时终止该进程。
如何从我的 shell 脚本中获取该进程的 PID?据我所知,变量 $!
包含当前脚本的 PID,而不是后台进程。
I start a background process from my shell script, and I would like to kill this process when my script finishes.
How to get the PID of this process from my shell script? As far as I can see variable $!
contains the PID of the current script, not the background process.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
您可以使用 jobs -l 命令获取特定的 jobL
在本例中,46841 是 PID。
来自
帮助工作
:jobs -p 是另一个仅显示 PID 的选项。
You can use the
jobs -l
command to get to a particular jobLIn this case, 46841 is the PID.
From
help jobs
:jobs -p
is another option which shows just the PIDs.$$
是当前脚本的 pid$!
是最后一个后台进程的 pid以下是 bash 会话的示例记录(
%1
指的是后台进程的序号,如jobs
所示):$$
is the current script's pid$!
is the pid of the last background processHere's a sample transcript from a bash session (
%1
refers to the ordinal number of background process as seen fromjobs
):杀死 bash 脚本的所有子进程的更简单方法:
-P
标志与pkill
和pgrep
的工作方式相同 - 它得到子进程,只有使用pkill
时,子进程才会被终止,而使用pgrep
时,子进程的 PID 会打印到 stdout。An even simpler way to kill all child process of a bash script:
The
-P
flag works the same way withpkill
andpgrep
- it gets child processes, only withpkill
the child processes get killed and withpgrep
child PIDs are printed to stdout.这就是我所做的。看看吧,希望能有所帮助。
然后只需运行它:
./bgkill.sh
当然具有适当的权限this is what I have done. Check it out, hope it can help.
Then just run it as:
./bgkill.sh
with proper permissions of coursepgrep
可以获取父进程的所有子 PID。正如前面提到的,$$
是当前脚本的 PID。因此,如果您想要一个能够自行清理的脚本,那么这应该可以解决问题:pgrep
can get you all of the child PIDs of a parent process. As mentioned earlier$$
is the current scripts PID. So, if you want a script that cleans up after itself, this should do the trick:您也许还可以使用 pstree:
这通常会给出“用户”所有进程的文本表示,而 -p 选项给出进程 ID。据我了解,它并不依赖于让进程由当前 shell 拥有。它还显示了叉子。
You might also be able to use pstree:
This typically gives a text representation of all the processes for the "user" and the -p option gives the process-id. It does not depend, as far as I understand, on having the processes be owned by the current shell. It also shows forks.
如果您在启动作业后无法直接获取 PID,您也可以尝试此操作并稍后获取 PID:
说明:
ps
获取所有进程(包括进程)的信息。命令grep
正在过滤您的命令,第二个 grep 是为了不检索 grep 本身的 pidtr
正在删除 cut 的重复空格cut
是获取带有 PID 的列(在本例中为 2)If you're not able to get the PID directly after starting the job, you could also try this and get the PID later:
Explanation:
ps
get information for all processes incl. commandgrep
is filtering for your command and the second grep is for not retrieving the pid of grep itselftr
is removing duplicate spaces for cutcut
is getting you the column with the PID (2 in this case)我在配置各种基础设施对象时多次遇到这个问题。很多时候,您需要使用 kubectl 的临时代理或临时端口转发。我发现 timeout 命令是一个很好的解决方案这些,因为它允许我的脚本是独立的,并且我可以确信该过程将会结束。我尝试设置较小的超时并重新运行脚本(如果我仍然需要它)。
I have run into this problem many times provisioning various infrastructure objects. Many times you need a temp proxy using kubectl or a temp port forward. I have found the timeout command to be a good solution for these, since it allows my script to be self contained and I can be assured that the process will end. I try to set small timeouts and rerun the script if I need still need it.
几年后,这里有一个查找命令 PID 的单行代码:
read -p "What is the name if the command to find PID of ?" pname ;职位-l | grep $pname | 查询awk '{ print "命令 PID 是 "$2}
它的作用:
询问进程名变量pname
列出所有作业并使用 grep 搜索 $pname
使用 awk 清晰地返回结果。
轻松修改以停止进程,例如,通过修改 awk 步骤并传递给 bash
read -p "What is the name if the command to find PID of ?" pname ;职位-l | grep $pname | 查询awk '{ 打印“kill”$2} | 对于任何进程/命令“foo”, bash
或非交互方式都非常简洁:
set pname=foo ;
职位-l | grep $pname | 查询awk '{ print "命令 PID 为 "$2}
但请注意,这假定只有一个名为 foo 的进程。万一出现这种情况,可以添加对答案数量的测试,如果数字大于 1,则提出进程 ID 列表
Some years late, here's a one-liner to find the PID of a command :
read -p "What is the name if the command to find PID of ? " pname ; jobs -l | grep $pname | awk '{ print "The command PID is "$2}
What it does :
Ask for the process name variable pname
list all jobs and search for $pname with grep
use awk to return the result legibly.
Easily amended to stop a process for example, by modifying the awk step and passing to bash
read -p "What is the name if the command to find PID of ? " pname ; jobs -l | grep $pname | awk '{ print "kill "$2} | bash
or non interactively for any process/command "foo" it's very succinct :
set pname=foo ;
jobs -l | grep $pname | awk '{ print "The command PID is "$2}
though note this assumes there is just one process named foo. In the unlikely event one were in that situation, one could add a test for number of answers, and if number greater than one, propose a list of process IDs
您需要在启动后台进程时保存它的 PID:
您无法使用作业控制,因为这是一项交互功能并且与控制终端相关联。脚本不一定有附加终端,因此作业控制不一定可用。
You need to save the PID of the background process at the time you start it:
You cannot use job control, since that is an interactive feature and tied to a controlling terminal. A script will not necessarily have a terminal attached at all so job control will not necessarily be available.