Last active
November 26, 2020 17:48
-
-
Save dualbus/9275406 to your computer and use it in GitHub Desktop.
How to detach processes from bash properly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Relevant section from ''man bash'', SIGNALS: | |
> The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, | |
> running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from send‐ | |
> ing the signal to a particular job, it should be removed from the jobs table with the disown builtin (see SHELL BUILTIN | |
> COMMANDS below) or marked to not receive SIGHUP using disown -h. | |
> | |
> If the huponexit shell option has been set with shopt, bash sends a SIGHUP to all jobs when an interactive login shell | |
> exits. | |
According to this, the proper way to detach a process from bash is the following: | |
$ command >/dev/null 2>&1 <&1 & disown | |
The redirections are needed. If you don't redirect to /dev/null, the | |
process will inherit the shell's descriptors, which will point to the | |
terminal. When this terminal closes, the descriptors will point to a | |
closed file, which will make the process crash if it tries to write | |
to them. | |
The disown is needed, because under some conditions the shell will | |
send a SIGHUP to all the jobs in the job table, which will kill the | |
"detached" process. And instead of ignoring SIGHUP in the detached | |
process, let's not send the signal to it in the first place. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
+ bash=/bin/bash | |
+ for flags in -c -ic -imc | |
+ /bin/bash -c '(echo :) & wait' | |
/bin/bash: line 0: echo: write error: Bad file descriptor | |
+ /bin/bash -c '(echo :) >/dev/null 2>&1 </dev/null & wait' | |
+ /bin/bash -c '(echo :) & disown; wait' | |
/bin/bash: line 0: echo: write error: Bad file descriptor | |
+ /bin/bash -c '(echo :) >/dev/null 2>&1 </dev/null & disown; wait' | |
+ SECONDS=0 | |
+ /bin/bash -c '{ sleep 5; echo a; } & disown; wait' | |
+ echo a0 | |
a0 | |
+ SECONDS=0 | |
+ /bin/bash -c '{ sleep 5; echo b; } & wait' | |
a | |
b | |
+ echo b5 | |
b5 | |
+ p=20825 | |
+ exec /bin/bash -c '{ trap "echo a" HUP; sleep 5; } & wait' | |
+ sleep 3 | |
+ kill -HUP 20825 | |
script: line 8: 20825 Hangup ( p=$BASHPID; { sleep 3; kill -HUP "$p"; } & exec "$bash" "$flags" '{ trap "echo a" HUP; sleep 5; } & wait' ) | |
+ p=20847 | |
+ exec /bin/bash -c '{ trap "echo a" HUP; sleep 5; } & disown; wait' | |
+ for flags in -c -ic -imc | |
+ sleep 3 | |
+ /bin/bash -ic '(echo :) & wait' | |
[1] 20854 | |
/bin/bash: line 0: echo: write error: Bad file descriptor | |
[1]+ Exit 1 ( echo : ) | |
+ /bin/bash -ic '(echo :) >/dev/null 2>&1 </dev/null & wait' | |
[1] 20856 | |
[1]+ Done ( echo : ) > /dev/null 2>&1 < /dev/null | |
+ /bin/bash -ic '(echo :) & disown; wait' | |
[1] 20858 | |
/bin/bash: line 0: echo: write error: Bad file descriptor | |
+ /bin/bash -ic '(echo :) >/dev/null 2>&1 </dev/null & disown; wait' | |
[1] 20860 | |
+ SECONDS=0 | |
+ /bin/bash -ic '{ sleep 5; echo a; } & disown; wait' | |
[1] 20863 | |
+ echo a0 | |
a0 | |
+ SECONDS=0 | |
+ /bin/bash -ic '{ sleep 5; echo b; } & wait' | |
[1] 20867 | |
+ kill -HUP 20847 | |
script: line 19: kill: (20847) - No such process | |
a | |
b | |
[1]+ Done { sleep 5; echo b; } | |
+ echo b5 | |
b5 | |
+ p=20896 | |
+ exec /bin/bash -ic '{ trap "echo a" HUP; sleep 5; } & wait' | |
+ sleep 3 | |
[1] 20899 | |
+ kill -HUP 20896 | |
Hangup | |
a | |
+ p=20919 | |
+ exec /bin/bash -ic '{ trap "echo a" HUP; sleep 5; } & disown; wait' | |
+ sleep 3 | |
[1] 20922 | |
+ for flags in -c -ic -imc | |
+ /bin/bash -imc '(echo :) & wait' | |
[1] 20925 | |
/bin/bash: line 0: echo: write error: Bad file descriptor | |
[1]+ Exit 1 ( echo : ) | |
+ /bin/bash -imc '(echo :) >/dev/null 2>&1 </dev/null & wait' | |
[1] 20927 | |
[1]+ Done ( echo : ) > /dev/null 2>&1 < /dev/null | |
+ /bin/bash -imc '(echo :) & disown; wait' | |
[1] 20929 | |
/bin/bash: line 0: echo: write error: Bad file descriptor | |
+ /bin/bash -imc '(echo :) >/dev/null 2>&1 </dev/null & disown; wait' | |
[1] 20931 | |
+ SECONDS=0 | |
+ /bin/bash -imc '{ sleep 5; echo a; } & disown; wait' | |
[1] 20934 | |
+ echo a0 | |
a0 | |
+ SECONDS=0 | |
+ /bin/bash -imc '{ sleep 5; echo b; } & wait' | |
[1] 20938 | |
+ kill -HUP 20919 | |
script: line 19: kill: (20919) - No such process | |
a | |
b | |
[1]+ Done { sleep 5; echo b; } | |
+ echo b5 | |
b5 | |
+ p=20970 | |
+ exec /bin/bash -imc '{ trap "echo a" HUP; sleep 5; } & wait' | |
+ sleep 3 | |
[1] 20973 | |
+ kill -HUP 20970 | |
script: line 8: 20970 Hangup ( p=$BASHPID; { sleep 3; kill -HUP "$p"; } & exec "$bash" "$flags" '{ trap "echo a" HUP; sleep 5; } & wait' ) | |
Hangup | |
a | |
+ p=20993 | |
+ exec /bin/bash -imc '{ trap "echo a" HUP; sleep 5; } & disown; wait' | |
+ sleep 3 | |
[1] 20996 | |
+ kill -HUP 20993 | |
script: line 19: kill: (20993) - No such process |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -x | |
bash=/bin/bash | |
# Do not run with -mc, or it'll bash you! | |
for flags in -c -ic -imc; do | |
("$bash" "$flags" '(echo :) & wait' >&-) | |
("$bash" "$flags" '(echo :) >/dev/null 2>&1 </dev/null & wait' >&-) | |
("$bash" "$flags" '(echo :) & disown; wait' >&-) | |
("$bash" "$flags" '(echo :) >/dev/null 2>&1 </dev/null & disown; wait' >&-) | |
(SECONDS=0; "$bash" "$flags" '{ sleep 5; echo a; } & disown; wait'; echo "a$SECONDS") | |
(SECONDS=0; "$bash" "$flags" '{ sleep 5; echo b; } & wait'; echo "b$SECONDS") | |
(p=$BASHPID; { sleep 3; kill -HUP "$p"; } & exec "$bash" "$flags" '{ trap "echo a" HUP; sleep 5; } & wait') | |
(p=$BASHPID; { sleep 3; kill -HUP "$p"; } & exec "$bash" "$flags" '{ trap "echo a" HUP; sleep 5; } & disown; wait') | |
done | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment