当输入不匹配时防止 grep 返回错误
我想在 bash 脚本中编写一段代码来检查程序是否已经在运行。 我有以下内容是为了搜索 bar 是否正在运行
foo=`ps -ef | grep bar | grep -v grep`
该
grep -v grep
部分是为了确保 ps 结果中不考虑“grep bar”
当 bar 未运行时, foo 正确为空。但我的问题在于,脚本有
set -e
一个标志,如果某些命令返回错误,则终止脚本。 事实证明,当 bar 未运行时,“grep -v grep”与任何内容都不匹配,并且 grep 返回错误。我尝试使用 -q 或 -s 但无济于事。
有什么解决办法吗?谢谢
I want to write in a bash script a piece of code that checks if a program is already running.
I have the following in order to search whether bar is running
foo=`ps -ef | grep bar | grep -v grep`
The
grep -v grep
part is to ensure that the "grep bar" is not taken into account in ps results
When bar isn't running, foo is correctly empty. But my problem lies in the fact tha the script has
set -e
which is a flag to terminate the script if some command returns an error.
It turns out that when bar isn't running, "grep -v grep" doesn't match with anything and grep returns an error. I tried using -q or -s but to no avail.
Is there any solution to that? Thx
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
当然:
或者甚至:
Sure:
Or even:
简短回答
请写下
如果您使用
set -e
,。如果您使用 bash 的
pipefail
选项 (set -o pipelinefail
),请记住应用异常处理 (||test) 到管道中的每个
grep
:在 shell 脚本中,我建议您使用“catch-1-grep” (c1grep) 实用程序功能:
解释
grep
的退出状态为 0、1 或 2: [1]0
表示选择了一行1
表示没有选择任何行grep
如果被信号中断,还可以返回其他代码(例如 SIGINT 的130
)。由于我们只想忽略退出状态
1
,因此我们使用test
来抑制该特定退出状态。grep
返回0
,则test
不会运行。grep
返回1
,则运行test
并返回0
。grep
返回任何其他值,则运行test
并返回1
。在最后一种情况下,脚本将由于
set -e
或set -o pipelinefail
立即退出。但是,如果您根本不关心grep
错误,您当然可以按照 肖恩。
[附加] shell 脚本中的用法
在 shell 脚本中,如果您经常使用
grep
,我建议您定义一个实用函数:这样您的管道会变得很短并且很长。又简单了,又不丢失
set -e
和set -o pipefail
的功能:仅供参考:
c1grep
来强调它只是捕获退出状态1
,没有别的。grep
(grep() { env grep "$@" ...; }
),但我更喜欢一个不那么混乱且更明确的名称,c1grep
。[附加]
ps
+grep
因此,如果您想知道如何避免
grep -v grep
甚至| grep
是ps|grep
的一部分,看看其他一些答案;但这有点题外话。[1]
grep
文档(POSIX 规范, GNU grep 文档,FreeBSD 联机帮助页)Short answer
Write
if you are using
set -e
.If you use bash's
pipefail
option (set -o pipefail
), remember to apply the exception handling (||test
) to everygrep
in the pipeline:In shell scripts I suggest you to use the ”catch-1-grep“ (c1grep) utility function:
Explained
grep
's exit status is either 0, 1 or 2: [1]0
means a line is selected1
means no lines were selected2
means an error occurredgrep
can also return other codes if it's interrupted by a signal (e.g.130
for SIGINT).Since we only want to ignore exit status
1
, we usetest
to suppress that specific exit status.grep
returns0
,test
is not run.grep
returns1
,test
is run and returns0
.grep
returns any other value,test
is run and returns1
.In the last case, the script will exit immediately due to
set -e
orset -o pipefail
. However, if you don't care aboutgrep
errors at all, you can of course writeas suggested by Sean.
[additional] usage in shell scripts
In shell scripts, if you are using
grep
a lot, I suggest you to define an utility function:This way your pipe will get short & simple again, without losing the features of
set -e
andset -o pipefail
:FYI:
c1grep
to emphasize it's simply catching exit status1
, nothing else.grep
instead (grep() { env grep "$@" ...; }
), but I prefer a less confusing and more explicit name,c1grep
.[additional]
ps
+grep
So if you want to know how to avoid
grep -v grep
or even the| grep
part ofps|grep
at all, take a look at some of the other answers; but this is somewhat off-topic imho.[1]
grep
documentation (POSIX spec, GNU grep docs, FreeBSD manpage)避免 grep -v grep 的一个好技巧是:
正则表达式仅匹配字符串“bar”。但是,在
ps
输出中,字符串“bar”不会随 grep 进程一起出现。在我学习
pgrep
之前的几天,我写了这个函数来自动化上面的命令:然后,
变成
A good trick to avoid
grep -v grep
is this:That regular expression only matches the string "bar". However in the
ps
output, the string "bar" does not appear with the grep process.In the days before I learned about
pgrep
, I wrote this function to automate the above command:Then,
turns into
如果您只想丢弃 99% 的输出,为什么还要要求
ps
使用-ef
提供大量输出呢?ps
,尤其是 GNU 版本,是一把功能方便的瑞士军刀。试试这个:我在这里指定
-o pid=
只是因为,但实际上这是没有意义的,因为我们无论如何都会扔掉所有的 stdout。不过,如果您想知道实际运行的 PID,这会很有用。如果
-C
无法匹配任何内容,ps
将自动返回非零存在状态,如果匹配则返回零。所以你可以简单地说这个或者
那不是更简单吗?不需要 grep,不需要两次甚至一次。
Why ask
ps
to provide massive amounts of output with-ef
if you only are going to throw away 99% of it?ps
and especially the GNU version is a swiss army knife of handy functionality. Try this:I specify
-o pid=
here just because, but in fact it's pointless since we throw away all of stdout anyway. It would be useful if you wanted to know the actual running PID, though.ps
automatically will return with a non-zero exist status if-C
fails to match anything and with zero if it matches. So you could simply say thisOr
Isn't that simpler? No need for grep, not twice or even once.
尝试这样做:
cat 始终返回 0 并忽略 grep 的退出代码
Try to make so:
cat returns always 0 and ignores exit code of grep
如果您使用 grep,所有这些都非常混乱,有时它找不到任何匹配项,而您只想继续。如果您安装了 ruby,则可以执行 ruby -ne 'print if /bar/',如果没有匹配项,它将没有输出。
All of it's pretty messy if you are using grep and it sometimes does not find any matches and you want to just continue. If you have ruby installed, you can do
ruby -ne 'print if /bar/'
, and it will just have no output if there are no matches.