如果$PID_PARENT
启动了$PID_CHILD
,我怎样才能分离(disown
?) ,$PID_CHILD
以便$PID_PARENT
当我杀死时$PID_PARENT
,$PID_CHILD
继续运行就像什么都没发生一样?
具体来说, my$PID_PARENT
是正在运行的进程Jenkins
(或Java
运行运行 Jenkins 的服务器的进程),并且$PID_CHILD
是真的很长我不想在重新启动 Jenkins 后重新启动作业(这是一些维护所需要的)。本质上,我想停止 Jenkins,但不想停止它开始的长期工作,而且我知道两个 PID。
更新1:我从登录 shell 中发现disown
并尝试过(所以不是父 PID shell):
disown $PID_CHILD
但得到了
-bash: disown: 13924: no such job
正确$PID_CHILD
和做的事
ps -o ppid= $PID_CHILD
回报$PID_PARENT
更新2:根据@Rui 的回答,我在 Jenkins 中做了一个临时 hack 工作,这次只从父 shell 运行:
disown 13924
但仍然得到了
disown: 13924: no such job
答案1
一种方法是让子进程与父进程解除关联。这会在子进程中需要合适的代码,或在执行实际代码之前执行解除关联的包装脚本:
#!/usr/bin/env perl
use strict;
use warnings;
die "Usage: $0 command [args ..]\n" unless @ARGV;
# diassociate this process (some folks also do a double-fork thing)
use POSIX "setsid";
chdir("/") || die "can't chdir to /: $!";
open( STDIN, "< /dev/null" ) || die "can't read /dev/null: $!";
open( STDOUT, "> /dev/null" ) || die "can't write to /dev/null: $!";
defined( my $pid = fork() ) || die "can't fork: $!";
exit if $pid; # non-zero now means I am the parent
( setsid() != -1 ) || die "Can't start a new session: $!";
open( STDERR, ">&STDOUT" ) || die "can't dup stdout: $!";
# and replace ourself with whatever we were called with
exec @ARGV;
如果保存为solitary
可以通过以下方式进行测试:
% ./solitary logger greppable
% grep greppable /var/log/system.log
Jun 27 10:52:15 hostn jhqdoe[20966]: greppable
%
因为logger(1)
标准文件句柄作为解除关联的一部分已全部关闭。这些可能需要重定向到您的应用程序的其他地方。
请注意,如果 Jenkins(或 systemd 或其他)使用 PID 命名空间,则该进程无论如何分叉都无法逃脱,这可能是不可能的,在这种情况下,您将需要一些容器级解决方案,或者重新审视您正在做的事情试图做。
答案2
我认为你应该能够简单地做
$ disown $PID
然后,如果您终止 shell 会话,该进程仍将运行。
答案3
您需要disown
从调用该进程的 shell 中执行操作。因此,从其他 shell 调用您会收到消息no such job
。
要真正否认进程并告诉它忽略挂断信号,您可以从调用该进程的 shell 执行以下操作:
disown -h $PID
来自 disown 帮助:
$ disown --help disown: disown [-h] [-ar] [工作规范 ... | pid ...]
从当前 shell 中删除作业。Removes each JOBSPEC argument from the table of active jobs. Without any JOBSPECs, the shell uses its notion of the current job. Options: -a remove all jobs if JOBSPEC is not supplied -h mark each JOBSPEC so that SIGHUP is not sent to the job if the shell receives a SIGHUP -r remove only running jobs Exit Status: Returns success unless an invalid option or JOBSPEC is given.
答案4
当创建一个在 Jenkins 构建完成后仍然存在的后台进程时,您需要注意Jenkins 进程树杀手。当构建退出时,进程树杀手会尝试终止与该构建相关的所有进程,即使这些进程已不再属于构建进程并且不再是构建进程的子进程。
上面的链接中有关于如何禁用特定作业或整个 Jenkins 的进程树杀手的说明。