pgrep在bash脚本中的奇怪行为

时间:2014-03-10 11:46:03

标签: macos bash jenkins grep

我有一个脚本可以杀死一个在linux上正常工作的进程树,但我在osx上遇到了一些奇怪的行为。它实际上适用于我的单元测试以及尝试在osx上手动运行时,但出于某种原因,当它作为jenkins工作运行时,它的行为方式不同。

所以这是当前的bash函数,带有一点调试回显和休眠:

killtree() {
  local _pid=$1
  local _sig=${2:--TERM}
  echo "Stopping ${_pid}"
  sleep 1
  kill -stop ${_pid} # stop parent to avoid creation of new children
  children=`pgrep -P ${_pid}`
  echo "Children=$children"
  sleep 1
  for _child in $children; do
      killtree ${_child} ${_sig}
  done
  echo "Killing child ${_pid}"
  sleep 1
  kill -${_sig} ${_pid}
}

调用pgrep,失败的运行可以pgrep -P 9651打印出机器上的所有进程,并且当脚本试图杀死pid 0时脚本挂起。

但为什么会得到所有流程呢?当运行完成时,进程9651仍然在运行,如果我在命令行pgrep -P 9651上发出命令,则根本没有输出(由于此进程应该没有子进程,所以预计会这样做。)

在这种情况下,尝试被杀死的进程是一个用于测试的简单sleep 10

我在列出子项之前添加了一个调试调用来打印进程树:

+ pstree='-+= 00001 root /sbin/launchd
 \-+= 09774 root /usr/sbin/sshd -i
   \-+- 09777 jenkins /usr/sbin/sshd -i
     \-+= 09783 jenkins bash -c cd '\''/var/jenkins'\'' && java  -jar slave.jar
       \-+- 09784 jenkins /usr/bin/java -jar slave.jar
         \-+- 09807 jenkins /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/bin/java -classpath/     
          \-+- 09817 jenkins /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/bin/java -
            \--- 09828 jenkins sleep 10'

对我来说很正常,sleep 10没有孩子。

任何想法 - 在尝试调试这几个小时后我有点卡住了?

(实际上我第一次在apple.stackexchange上发布,因为我只在osx上看到它,但是这可能是一个更好的地方,因为我的默认情况下我的pxp甚至不存在于osx中)

1 个答案:

答案 0 :(得分:1)

一些搜索显示jenkins在修改后的环境PATH下运行任务(可能出于安全原因)。您需要确保:

  • pgrep安装在您的系统上(较旧的OSX版本没有它,它可以在Apple Developer&'s Tools中找到)
  • pgrep在路上。

或者,如果您在jenkins下修改PATH有困难,可以编辑脚本以包含完整的pgrep路径

首先确定你的pgrep在用户tty shell下的运行位置:

$ which pgrep
/opt/local/bin/pgrep

变化:

children=`pgrep -P ${_pid}`

要:

children=`/opt/local/bin/pgrep -P ${_pid}`

其他shell命令(echo,sleep,kill等)应该由命令shell本机解释,并且应该'不需要路径。