我尝试了ps并按名称进行过滤,但是我无法按名称区分进程。
myCommand
ps ux | awk '/<myCommand>/ {print }'
因为进程名称不是唯一的。 />
我可以通过以下方式运行进程:
myCommand &
我发现我可以通过以下方式获取此PID:
echo $!
有没有更简单的解决方案?
我很乐意执行myCommand并通过一行命令获得其PID。
#1 楼
有什么比echo $!
更简单的?作为一行:myCommand & echo $!
#2 楼
您甚至可以在运行命令之前使用sh -c
和exec
来获取命令的PID。要启动
myCommand
,以便在开始运行之前打印其PID,可以使用:sh -c 'echo $$; exec myCommand'
工作原理:
这将启动一个新的shell,打印该shell的PID,然后使用内置的
exec
用您的命令替换该shell,确保它具有相同的PID。当您的shell运行带有内置exec
的命令时,您的shell实际上正在成为该命令,而不是派生自己的新副本的更常见的行为,该副本具有自己独立的PID,然后成为命令。我发现,这比涉及异步执行(使用
&
),作业控制或使用ps
进行搜索的方法要简单得多。这些方法很好,但是除非您有特定的理由使用它们(例如,也许该命令已经在运行,在这种情况下搜索其PID或使用作业控制才有意义),我建议您首先考虑采用这种方法。 (而且我当然不会考虑编写复杂的脚本或其他程序来实现此目的。)此答案包括此技术的示例。
各部分
即使您使用的shell是Bourne风格的,因此支持具有这些语义的
exec
内置命令,您通常也不应该避免为此,请使用sh -c
(或等效命令)创建一个新的单独的shell进程,因为:一旦shell变为
myCommand
,就没有shell等待运行后续命令了。将sh -c 'echo $$; exec myCommand; foo
替换为foo
后,将无法尝试运行myCommand
。除非您编写的脚本是最后一个运行该脚本的脚本,否则不能仅在运行其他命令的shell中使用echo $$; exec myCommand
。您不能为此使用子外壳。
(echo $$; exec myCommand)
在语法上可能比sh -c 'echo $$; exec myCommand'
更好,但是当您在$$
(
内运行)
时,它将给出父外壳的PID,而不是子外壳本身的PID。但是,子外壳的PID将成为新命令的PID。一些外壳程序提供了自己的非便携式机制来查找子外壳程序的PID,您可以将其用于此目的。尤其是在Bash 4中,(echo $BASHPID; exec myCommand)
确实可以工作。最后,请注意,某些shell在执行命令时会执行优化,就像
exec
一样(即,它们首先放弃分叉)(已知时)这样,shell之后便无需执行任何操作。一些shell会尝试在它是最后一个要运行的命令时执行此操作,而其他shell只会在该命令之前或之后没有其他命令时执行此操作,而其他shell则根本不会执行。这样做的结果是,如果您忘记编写exec
而仅使用sh -c 'echo $$; myCommand'
,那么在某些具有某些shell的系统上,有时它会为您提供正确的PID。我建议您不要再依赖这种行为,而是在需要时始终添加exec
。评论
在运行myCommand之前,需要在bash脚本中设置许多环境变量。这些会继续执行exec命令的环境吗?
–user5359531
18年5月11日在15:41
看起来我的环境确实继承了exec命令。但是,当myCommand启动您需要使用的其他进程时,该方法不起作用。当我发出以这种方式获取pid的kill -INT
–user5359531
18年5月11日在16:43
我试过了,但是myCommand进程的pid似乎是echo $$ +1所输出的pid。难道我做错了什么?
– crobar
18年8月28日在10:13
我的命令如下:sh -c'echo $$; exec / usr / local / bin / mbdyn -f“ input.file” -o“ / path / to / outputdir”>“ command_output.txt” 2>&1&'
– crobar
18年8月28日在10:51
这很棒,但是当我尝试将回显的值转换为变量时,它对我不起作用,因此我以后可以实际使用它来终止该过程,例如PID = $(sh -c'echo $$; exec myCommand')只是挂起,而如果我删除PID = $(...)包装器,它将显示PID并立即继续!
–迈克尔
20 Apr 16'0:22
#3 楼
将命令包装在一个小的脚本中#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file
#4 楼
我不知道有任何更简单的解决方案,但是没有使用$!够好了?正如其他人所说,如果以后需要,您可以始终将值分配给其他变量。作为补充,可以使用
pgrep
或pidof
代替ps的管道。#5 楼
将pid注册到文件后,使用bash脚本中的exec:示例:
假设您有一个要与args一起运行的名为“ forever.sh”的脚本p1,p2,p3
forever.sh源代码:
#!/bin/sh
while [ 1 -lt 2 ] ; do
logger "#!/bin/sh
echo $$ > /var/run/.pid
exec "$@"
running with parameters \"$@\""
sleep 5
done
创建收割者。sh:
./reaper.sh ./forever.sh p1 p2 p3 p4 &
通过reaper.sh永久运行以下命令:
cat /var/run/forever.sh.pid
5780
现在,您在/var/run/forever.sh.pid中有了pid。
syslog grep:
Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"
您可以在进程表中看到它:
ps axuwww|grep 'forever.sh p1' |grep -v grep
root 5780 0.0 0.0 4148 624 pts/7 S 16:07 0:00 /bin/sh ./forever.sh p1 p2 p3 p4
评论
哦,还有“ oneliner”:/ bin / sh -c'echo $$> / tmp / my.pid && exec program args'&
–user237419
2010-11-24 14:28
要在参数中正确保留内部空格,应使用exec“ $ @”而不是exec $ *。从技术上讲,您需要保留的不是空格,而是IFS shell参数(默认为空格,制表符和换行符)中字符的出现。
–克里斯·约翰森(Chris Johnsen)
2010-11-25 3:53
点。 :)
–user237419
10 Nov 25'7:54
谢谢,我不知道$$参数。这可能非常有用。
–rafalmag
10-11-27在12:12
#6 楼
在bash shell中,$!
的替代方法可能是内置的jobs -p
。在某些情况下,!
中的$!
在(而不是在)变量扩展之前被shell解释,从而导致意外结果。例如,这将不起作用:((yourcommand) & echo $! >/var/run/pidfile)
而这将是:
((yourcommand) & jobs -p >/var/run/pidfile)
评论
我认为您的意思是((yourcommand)&jobs -p> / var / run / pidfile)。
–Dom
17年11月13日在20:33
#7 楼
您可以使用以下命令:$ myCommand ; pid=$!
或
$ myCommand && pid=$!
这两个命令可以使用
;
或&&
。在第二种情况下,仅当第一个命令成功时才设置pid。您可以从$pid
获取进程ID。评论
OP希望获取PID,以便稍后可以杀死它。 ;和&&要求在回显$!之前退出原始过程!被执行。
–user9517
2010-11-24 8:58
是的,你是对的。 myCommand终止后,这将为您提供pid。
–卡乐德
2010-11-24 9:02
引用$!在&&或;之后永远不会给您命令分隔符左侧开始的进程的PID。 $!仅为异步启动的进程设置(例如,通常使用&,但某些shell也具有其他方法)。
–克里斯·约翰森(Chris Johnsen)
2010年11月24日,9:47
这很有帮助,为什么除了我之外没有人投票?不错,虽然:)
–寺庙
16-09-28在21:14
#8 楼
这有点不合逻辑,对大多数人来说不太可能。这也是一个巨大的安全风险方法,因此,除非您确定自己会安全并且输入已被清理,然后...明白,否则不要这样做。编译将小C程序转换成名为
start
(或您想要的任何名称)的二进制文件,然后以./start your-program-here arg0 arg1 arg2 ...
的身份运行程序。长话短说,这将把PID打印到stdout
,然后将程序加载到进程中。它应该仍然具有相同的PID。评论
如何在bash变量中记录此代码返回的PID号?由于我不清楚的原因,此示例中似乎未记录stdout:RESULT =“ $(./ start_and_get_pid.out echo yo)”;回声“ $ RESULT”
– Tfb9
18年11月8日在1:27
@ Tfb9:老实说,我推荐其他方法之一。我在2年前写了这篇文章,到目前为止,它是目前所介绍的骇客/容易出错的方法之一(或者我认为)。
–tonysdg
18年11月8日在1:30
感谢您的来信。我想我通过睡眠10和PID_IS = $!解决了我的问题。回声$ PID_IS
– Tfb9
18年11月9日,0:33
评论
谢谢您将这些命令与“&”合并对我有很大帮助。
–rafalmag
2010-11-27 12:09
在bash脚本中,在启动程序的循环中,$!是不准确的。有时它返回脚本本身的pid,有时从脚本中返回grep或awk运行的任何解决方案,以专门获取在这种情况下刚启动的进程的pid?像pid = myprogram这样的东西真棒
–user217730
2014年4月26日在5:59
注意,这要求您使用&作为上一行来启动命令,否则echo基本上返回空白。
–rogerdpack
15年2月4日在18:56
分配给像command&echo $这样的变量!在这一步冻结执行:(
– Shashank Vivek
16年7月15日在9:41
如果您没有明确后台该过程,则此方法不起作用!例如,您的进程在完成需要继续执行的操作之前可能会使其本身成为后台。
–迈克尔
20年4月16日在0:10