如何将“pgrep”的输出与“ps -p”一起使用?

jus*_*lin 3 command-line bash scripts conky

我正在尝试显示 Conkys 进程的正常运行时间。如果我在终端中一次一行输入以下内容,那么一切都会正常工作,并且我会得到我想要的结果。

getPID=$(pgrep -f conky)

conkyPID=$(ps -p $getPID -o etime=)

echo $conkyPID
Run Code Online (Sandbox Code Playgroud)

天真的我以为 bash 脚本会是这样的。

#!/bin/bash
getPID=$(pgrep -f conky)
conkyPID=$(ps -p "$getPID" -o etime=)
echo "$conkyPID"
Run Code Online (Sandbox Code Playgroud)

我问了几个朋友,我收到的最有用的信息是我需要一个命令行分隔符,我认为它是一个|. 我尝试了很多括号、引号和管道的变体,但都无济于事。在我的实验中,第二行似乎不知道我在前一行中设置了变量“getPID”。当我运行脚本时,我得到了。

error: process ID list syntax error
Run Code Online (Sandbox Code Playgroud)

运行脚本的输出bash -x

ricky@Shitmobile:~$ bash -x conkypid.sh
++ pgrep -f conky 
+ getPID='45990
153098'
++ ps -p '45990 153098' -o etime=
error: process ID list syntax error 
Run Code Online (Sandbox Code Playgroud)

Art*_*ild 5

在您的情况下,由于每一行都是一个单独的命令,因此没有任何区别 - 脚本应该可以工作:(请注意,$getPID并且$conkyPID应该被引用)

#!/bin/bash
getPID=$(pgrep -f conky)
conkyPID=$(ps -p "$getPID" -o etime=)
echo "$conkyPID"
Run Code Online (Sandbox Code Playgroud)

我已经测试过,这对我来说效果很好。

但是,由于pgrep可以返回多个值作为输出(这在您的情况下是正确的),因此您应该隔离输出,以便只获取最早的 PID。所以修改如下:

#!/bin/bash
getPID=$(pgrep -fo conky)
# getPID=$(pgrep -f conky | head -n 1) # another, but not as elegant method
conkyPID=$(ps -p "$getPID" -o etime=)
echo "$conkyPID"
Run Code Online (Sandbox Code Playgroud)

这只会获取 conky 的第一个 PID,并显示该 PID 的运行时间。

另一方面,如果您希望处理可能由 输出的所有 PID pgrep,那么您可以将输出通过管道传输到,如下所示xargsps

#!/bin/bash
getPID=$(pgrep -f conky)
conkyPID=$(ps -p "$getPID" -o etime=)
echo "$conkyPID"
Run Code Online (Sandbox Code Playgroud)

两者一次-I _只处理一个参数行(pgrep默认在换行符上输出每个 PID)并将其传递到ps -p _ ...占位符的就地/位置_。...您还可以通过命令替换直接将值分配给变量,甚至可以像这样缩短脚本:

#!/bin/bash
getPID=$(pgrep -fo conky)
# getPID=$(pgrep -f conky | head -n 1) # another, but not as elegant method
conkyPID=$(ps -p "$getPID" -o etime=)
echo "$conkyPID"
Run Code Online (Sandbox Code Playgroud)