我想判断某个进程是否正在运行。该进程的描述很长,大致如下
/usr/bin/xpdf -remote myXpdfServer -title Bayes2_notes -papercolor cornsilk -geometry 1910x1019+0+29 /home/simon/research/Ward/Bayes2_notes.pdf
我有时必须使用列数较少的 xterm,例如 n。在这种情况下,如果我运行 ps -ef,然后 grep 此字符串尾部远处的某个元素,ps 会截断该字符串,仅返回前 n 个字符,并且我的 grep 命令会失败。
为了解决这个问题,我尝试了 ps efo cmd | grep 等等。这有些帮助,但效果不如我所愿。例如,尝试以下显而易见的命令:
ps eco cmd | grep xpdf | grep -v grep
返回以下内容:
|.................................\_ /usr/bin/xpdf -remote myXpdfServer
其中的点表示空格,这些空格不会出现在本论坛中。我非常想删除垃圾,尤其是开头的空格,即 /usr 之前的所有内容。请注意,在这种情况下,管道到 cut 或 sed 或其他东西不会有帮助:ps 返回的字符串的长度由 xterm 列的数量决定,因此通过后处理缩短此字符串对我没有帮助,因为当 cut 开始执行其操作时,我需要检查的字符串已经被截断。我确信做我想做的事情的唯一方法是向 ps ef 命令添加一些其他标志。
非常感谢您的建议!
答案1
ps -ww
提供无限宽度的输出。您可以根据需要 grep 任意多的命令行。如果您在字符串前加上前缀以匹配,[ ]
则 grep 将不会匹配自身。如果将 -q 添加到 grep,则没有输出,但您可以使用返回代码:如果找到,则返回代码为 0,否则为 1。因此
if ps alxww | grep -q '[ ]/usr/bin/xpdf -remote myXpdfServer -title Bayes2_notes -papercolor cornsilk -geometry 1910x1019+0+29 /home/simon/research/Ward/Bayes2_notes.pdf'
then echo running
else echo not
fi
grep 实际上匹配的是模式,而不是确切的字符串。模式中有一些“魔法”字符,它们本身并不代表任何含义。幸运的是,您要 grep 的命令行字符串没有魔法字符,因此您的模式只是与字符串完全匹配。一些魔法字符是[
、*
、.
、(
、+
。特别是,该模式[ ]
意味着匹配空格字符。因此,它显然是一个毫无意义的模式,因为它与单独的空格相同:“ ”。
但正如你所知,执行ps|grep string
会找到 grep 命令以及我们感兴趣的命令。但通过使用[ ]
,grep 将不再匹配其自己的命令,因为在 ps 的输出中将有 3 个字符“[ ]”而不是单个字符“”,因此图案(1 个空格)将不匹配。
这有点难以理解。你可以阅读关于模式的文章,它们被称为常用表达,在man grep
。它们非常有用。
执行此操作时,isRunning=$(ps -ef | grep -q '[ ]xpdf ')
变量将设置为空字符串,因为grep -q
不会产生任何输出。shell 运行的最后一个命令的返回代码可在 shell 变量中找到$?
。如果为真,即 grep 匹配,则返回 0,否则返回非零(通常为 1)。预期值显示在退出状态的部分 man grep
。
因此,如果您想保留结果,您可以这样做,例如:
ps -ef | grep -q '[ ]xpdf '
isRunning=$?
if [ $isRunning = 0 ]
then echo "running. isRunning=$isRunning"
else echo "not. isRunning=$isRunning"
fi