grep 命令给出误报结果

grep 命令给出误报结果

我使用此命令来获取以特定名称(在循环中)运行的任何进程的计数,然后进一步确定计数,但有时它会为所有进程提供错误的答案,有时会为同一循环中的少数进程提供错误的答案。在某些服务器上根本不会有任何问题。当我手动检查相同内容时,结果发现是错误的

check_process() {
    process_count=$(ps -eaf | grep -v grep | grep "$1" | wc -l)
    if [ "${process_count}" -eq 1 ]; then
        PROCESS_EXISTS=0
        echo $1 " is running"
    else
        PROCESS_EXISTS=1
        echo $1 " is not running"
    fi
}

我还想提一下,它曾经工作得很好,近两年了,直到最近 2-3 个月才开始出现问题。

答案1

ps -f给出如下输出:

chazelas   11042   10528  1 08:49 ?        00:00:03 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -prefsLen 7847 -prefMapSize 699608 -parentBuildID 20200720193547 -appdir /usr/lib/firefox/browser 10528 true tab

grep "$1"在许多帐户上,返回给定进程名称的行是错误的:

  • $1如果以 开头,则会失败-。你需要grep -e "$1"grep -- "$1".在将任意数据传递给命令时,您确实应该养成使用选项结束定界符的习惯。
  • grep采用正则表达式模式进行匹配(即rein grep)。例如,因此grep a.py会匹配。aspy您可以使用grep -F来搜索子字符串。
  • ps -f不报告过程名字但过程论点(包括argv[0]按照惯例通常是命令的路径)。
  • 您正在查找正则表达式/子字符串,而不限制它匹配的行内的位置。例如,上面的$1==as会匹配asin 。或者它可以匹配除 之外的其他参数。chazelasargv[0]
  • grep | wc -lgrep -c

这里,有一个(非标准但非常常见)命令来按名称(或其他重要标准)匹配进程:pgrep

pgrep -xc -- "$1"

c计算哪些进程姓名ps(就像without报告的那样-f)ex正好匹配 中的正则表达式$1。使用-f,pgrep匹配完整的参数列表(由 报告ps -f)而不是进程名称。

这就留下了进程名称包含正则表达式运算符的问题(如上所述.)。不幸的是,pgrep没有-F选项可以进行字符串比较而不是正则表达式匹配,因此您需要转义其中的正则表达式运算符。

另一种选择是告诉ps仅报告进程名称,然后用于grep -xF执行x固定F字符串比较:

ps -Ao comm= | grep -Fxce "$1"

替换commargs打印参数列表(尽管可能被截断,某些ps实现允许一个或多个参数-w提高行长度限制)而不是进程名称。

在任何情况下,任何用户都可以使用任何名称和任何参数列表创建任何进程,因此按名称查找进程非常脆弱。任何人都可以通过启动具有相同名称和相同参数列表的进程来运行完全不同的命令,从而欺骗您认为您的进程就在那里。

通常最好检查您的流程提供的服务的可用性或保留其当前正在使用的某些资源。

在某些情况下,您可以在搜索中添加其他条件,例如有效 uid ( -uin pgrep) 或当前正在运行的可执行文件的路径。

在 Linux 上并使用zsh

pids=(/proc/<->(Nnu[chazelas]e['[[ $REPLY/exe -ef /usr/bin/sleep ]]']:t]))

例如,将以用户身份存储在文件$pids中运行代码的进程的 ID中,您可以使用它来检查该列表是否不为空。 (用或替换以搜索中的命令)。/usr/bin/sleepchazelasif (($#pids > 0)); then.../usr/bin/sleep=sleep$commands[sleep]sleep$PATH

更一般地说,最好依靠服务经理来管理服务和流程。现代的诸如此类systemd将提供可靠地做到这一点的设施。

答案2

  1. 在某些情况下可能会出现一些奇怪的时间效应。
  2. 根据您要查找的内容,可能还有其他匹配项。如果没有wc.由于您检查的方式,如果有两个匹配项,您会报告它没有运行。 (即考虑使用-ge而不是-eq。)
  3. 更有效的测试可以是使用killall -0 commandname.使用信号 0 进行终止不会发送实际信号,但仍会进行所有错误检查,包括如果未发现任何内容则显示错误。 (一个缺点:终止不属于您自己的进程也是一个错误,除非您是 root。该--user选项可以帮助解决此问题。)

相关内容