我想在bash脚本中编写一段代码,用于检查程序是否已在运行.我有以下内容,以搜索栏是否正在运行
foo=`ps -ef | grep bar | grep -v grep`
Run Code Online (Sandbox Code Playgroud)
该
grep -v grep
Run Code Online (Sandbox Code Playgroud)
部分是为了确保在ps结果中不考虑"grep bar"
当bar未运行时,foo正确为空.但我的问题在于剧本的事实
set -e
Run Code Online (Sandbox Code Playgroud)
如果某个命令返回错误,则为终止脚本的标志.事实证明,当bar未运行时,"grep -v grep"与任何内容都不匹配,grep会返回错误.我尝试使用-q或-s但无济于事.
那有什么解决方案吗?谢谢
Sea*_*ean 63
当然:
ps -ef | grep bar | { grep -v grep || true; }
Run Code Online (Sandbox Code Playgroud)
甚至:
ps -ef | grep bar | grep -v grep | cat
Run Code Online (Sandbox Code Playgroud)
gle*_*man 15
要避免的一个好方法grep -v grep是:
ps -ef | grep '[b]ar'
Run Code Online (Sandbox Code Playgroud)
该正则表达式仅匹配字符串"bar".但是在ps输出中,字符串"bar"不会出现在grep进程中.
在我了解之前的几天pgrep,我写了这个函数来自动执行上面的命令:
psg () {
local -a patterns=()
(( $# == 0 )) && set -- $USER
for arg do
patterns+=("-e" "[${arg:0:1}]${arg:1}")
done
ps -ef | grep "${patterns[@]}"
}
Run Code Online (Sandbox Code Playgroud)
然后,
psg foo bar
Run Code Online (Sandbox Code Playgroud)
变成
ps -ef | grep -e '[f]oo' -e '[b]ar'
Run Code Online (Sandbox Code Playgroud)
myr*_*rdd 12
写
ps -ef | grep bar | { grep -v grep || test $? = 1; }
Run Code Online (Sandbox Code Playgroud)
如果你正在使用set -e.
如果使用bash的pipefailoption(set -o pipefail),请记住将异常处理(||test)应用于grep管道中的每个:
ps -ef | { grep bar || test $? = 1; } | { grep -v grep || test $? = 1; }
Run Code Online (Sandbox Code Playgroud)
在shell脚本中,我建议你使用"catch-1-grep"(c1grep)实用程序函数:
c1grep() { grep "$@" || test $? = 1; }
Run Code Online (Sandbox Code Playgroud)
grep退出状态为0,1或2:[1]
0 表示选择了一条线1 表示没有选择任何行2 表示发生错误grep如果被信号中断(例如130SIGINT),也可以返回其他代码.
由于我们只想忽略退出状态1,因此我们使用它test来抑制特定的退出状态.
grep返回0,test则不运行.grep返回1,test则运行并返回0.grep返回任何其他值,test则运行并返回1.在最后一种情况下,由于set -eor ,脚本将立即退出set -o pipefail.但是,如果你根本不关心grep错误,你当然可以写
ps -ef | grep bar | { grep -v grep || true; }
Run Code Online (Sandbox Code Playgroud)
正如肖恩所说.
在shell脚本中,如果您经常使用grep,我建议您定义一个实用程序函数:
# "catch exit status 1" grep wrapper
c1grep() { grep "$@" || test $? = 1; }
Run Code Online (Sandbox Code Playgroud)
这样,你的管道将获得短期和简单再次,不失的特点set -e和set -o pipefail:
ps -ef | c1grep bar | c1grep -v grep
Run Code Online (Sandbox Code Playgroud)
供参考:
c1grep强调它只是捕捉退出状态1,没有别的.grep而不是(grep() { env grep "$@" ...; }),但我更喜欢一个不那么混乱和更明确的名字c1grep.[1]手册grep页
Sor*_*gal 10
如果您只是要扔掉99%的产品,为什么要求ps提供大量的产出-ef呢?ps特别是GNU版本是瑞士军刀的便利功能.试试这个:
ps -C bar -o pid= 1>/dev/null
Run Code Online (Sandbox Code Playgroud)
我-o pid=在这里指的只是因为,但事实上它是毫无意义的,因为无论如何我们扔掉了所有的stdout.但是,如果您想知道实际运行的PID,那将非常有用.
ps如果-C无法匹配任何内容,将自动返回非零存在状态,如果匹配,则返回零.所以你可以这么说
ps -C bar 1>/dev/null && echo bar running || echo bar not running
Run Code Online (Sandbox Code Playgroud)
要么
if ps -C bar 1>/dev/null ; then
echo bar running
else
echo bar not running
fi
Run Code Online (Sandbox Code Playgroud)
这不是更简单吗?不需要grep,不需要两次甚至一次.