Disowning child from parent process

disownJenkinsprocess

If $PID_PARENT launched $PID_CHILD, how can I detach (disown?) $PID_CHILD from $PID_PARENT so that, when I kill $PID_PARENT, $PID_CHILD keeps running like nothing happened?

Concretely, my $PID_PARENT is the process running Jenkins (or the Java process that runs the server that runs Jenkins) and $PID_CHILD is a reeeeeeally long job that I don't want to have to restart after restarting Jenkins (which is needed for some maintenance). Essentially, I want to stop Jenkins but not stop the long job it started and I know both PIDs.

UPDATE 1: I found out about disown and tried from a login shell (so not the parent PID shell):

disown $PID_CHILD

but got

-bash: disown: 13924: no such job

The $PID_CHILD correct and doing

ps -o ppid= $PID_CHILD

returns $PID_PARENT

UPDATE 2: As per @Rui's answer, I made a temporary hack job in Jenkins that only runs, from the parent shell this time:

disown 13924 

but still got

disown: 13924: no such job – amphibient

Best Answer

One way is to have the child process disassociate itself from the parent. This will require suitable code in the child process, or a wrapper script that performs the disassociation before executing the real code:

#!/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;

which if saved as solitary can be tested via something like:

% ./solitary logger greppable
% grep greppable /var/log/system.log
Jun 27 10:52:15 hostn jhqdoe[20966]: greppable
% 

with the use of logger(1) because the standard filehandles were all closed as part of the disassociation. These may need to be redirected elsewhere for your application.

Note that this may not be possible if Jenkins (or systemd or whatever) uses a PID namespace that the process cannot escape no matter how it forks itself, in which case you would need some container-level solution, or to revisit what you're trying to do.