【问题标题】:How to kill a process by reading from pid file using bash script in Jenkins?如何通过在 Jenkins 中使用 bash 脚本读取 pid 文件来终止进程?
【发布时间】:2017-11-19 01:01:19
【问题描述】:

Jenkins 中,我必须运行 2 个单独的脚本:start.shstop.sh。这些脚本在我的应用程序中,它是从 SCM 获取的。它们在同一个目录中。

start.sh 脚本使用 nohup 在后台运行一个进程,并将processId 写入save_pid.pid。这个脚本工作正常。它成功启动了我的应用程序。

然后在 stop.sh 中,我试图从save_pid.pid 读取processId 以删除该进程。但是,我无法删除进程并且应用程序继续运行,直到我使用手动终止进程:sudo kill {processId}

这是我迄今为止在 stop.sh 中尝试过的方法,但这些方法都不起作用:

kill $(cat /path/to/save_pid.pid)

kill `cat /path/to/save_pid.pid`

kill -9 $(cat /path/to/save_pid.pid)

kill -9 `cat /path/to/save_pid.pid`

pkill -F /path/to/save_pid.pid

我也用sudo 尝试了所有这些步骤。但是,它只是行不通。我在 stop.sh 中保留了一个 echo 语句,它会打印出来然后什么都没有。

我在这里做错了什么?

更新:

我在 start.sh 中使用的nohup 命令是这样的:

nohup deploy_script > $WORKSPACE/app.log 2>&1 & echo $! > $WORKSPACE/save_pid.pid

请注意:

就我而言,save_pid.pid 中写入的值令人惊讶 总是比实际 processId 的值小 1。 !!!

【问题讨论】:

  • 你确定/path/to/save_pid.pid的内容真的是你要杀死的进程的PID吗?
  • 是的,我想是的。由于 stop.sh 不起作用,我手动读取了 save_pid.pid 的内容,然后自己使用:sudo kill {processId} 删除了该进程。之后应用程序停止。所以,我猜它是正确的 pid。
  • 你检查脚本的错误输出了吗?如果kill 由于某种原因失败,它应该会产生一条错误消息,应该提供一些线索。
  • 正如您在第一条评论中所建议的,我刚刚注意到一些奇怪的事情。当我检查时,save_pid.id 中的值:它总是比实际的processId 小 1,我的意思是总是!!! .我发现实际上,在 start.sh 内部,nohup 在端口 9005 中运行我的应用程序。当我列出所有打开的端口和相应的进程时,我看到了一个 processId 对应于9005,只比save_pid.id的内容多1个。这怎么可能 ?而且,我还检查了运行 stop.sh 的输出。令人惊讶的是,除了我保留在那里的 echo 声明之外什么都没有。
  • 请注意,错误将被打印到stderr,而不是stdout。如果您找不到打印stderr 的位置,您可以暂时重定向它以进行调试,写为kill -9 ... 2>&1。至于为什么 PID 不同,似乎无论创建 PID 文件,它都没有正确执行。 (未写入正确的 PID 以终止进程以关闭进程。)

标签: linux bash jenkins


【解决方案1】:

我认为发生这种情况的原因是因为您没有获得您感兴趣的进程的PID,而是shell执行您的命令的PID .

看:

$ echo "/bin/sleep 10" > /tmp/foo
$ chmod +x /tmp/foo
$ nohup /tmp/foo & echo $!
[1] 26787
26787
nohup: ignoring input and appending output to 'nohup.out'
$ pgrep sleep
26789

所以 'nohup' 将执行 'shell','shell' 将派生第二个 'shell' 来执行 'sleep',但是我在这里只能计算两个进程,所以我无法解释创建的一个PID。

请注意,如果您将 nohup 和 pgrep 放在一行中,那么 pgrep 显然会比 'exec's 'sleep' 的 shell 启动得更快,因此 pgrep 不会产生任何结果,这在一定程度上证实了我的理论:

$ nohup /tmp/foo & echo $! ; pgrep sleep
[2] 26899
nohup: ignoring input and appending output to 'nohup.out'
$

如果您直接启动您的进程,那么 nohup 将“执行”您的进程,从而为该进程保留与 nohup 本身相同的 PID(请参阅http://sources.debian.net/src/coreutils/8.23-4/src/nohup.c/#L225):

$ nohup /bin/sleep 10 & echo "$!"; pgrep sleep
[1] 27130
27130
nohup: ignoring input and appending output to 'nohup.out'
27130

此外,如果您在脚本中“执行”“睡眠”,则只会创建一个进程(如预期的那样):

$ echo "exec /bin/sleep 10" > /tmp/foo
$ nohup /tmp/foo & echo "$!"; pgrep sleep
[1] 27309
27309
nohup: ignoring input and appending output to 'nohup.out'
27309

因此,根据我的理论,如果您在脚本中“执行”您的进程,那么您将获得正确的 PID。

【讨论】:

  • 我试过了:nohup deploy_script > $WORKSPACE/app.log 2>&1 & echo $! > $WORKSPACE/save_pid.pid; pgrep sleep,但没用。实际上,创建的 Id 和实际 Id 的差异现在是 2。
  • 从某种意义上说,即使在我的 nohup 脚本中添加了pgrep sleep,正如我在之前的评论中所展示的那样,我仍然无法在save_pid.pid 中获得准确的processId .
  • pgrep sleep 无助于为您提供进程的 PID。 PID 关闭了 2,因为显然您获得的 PID 是执行脚本的 shell 的 PID,而 not 是您正在启动的进程的 PID。要获取您正在启动的进程的PID,您需要在脚本inside输出echo $!
  • 好的。我的问题是,我无法修改deploy_script。每次运行应用程序时,它都会由我的应用程序的构建系统自动生成。你建议我在这种情况下应该怎么做?我仍然需要在后台运行脚本。
  • nohup deploy_script > $WORKSPACE/app.log 2>&1 & echo $(( $! - 1 )) > $WORKSPACE/save_pid.pid 但这肯定是一个丑陋的黑客!
猜你喜欢
  • 2012-07-25
  • 2011-12-10
  • 2010-10-06
  • 2017-08-04
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多