disown
is a shell builtin which tells bash to remove a process from its recordkeeping -- including the recordkeeping that forwards HUP signals. Consequently, if stdin, stdout and stderr are all redirected or closed before the terminal disappears, there's absolutely no need for nohup
so long as you use disown
.
#!/bin/bash
logfile=nohup.out # change this to something that makes more sense.
[ -t 1 ] && exec >"$logfile" # do like nohup does: redirect stdout to logfile if TTY
[ -t 2 ] && exec 2>&1 # likewise, redirect stderr away from TTY
{ prog <&3 3<&- & } 3<&0
disown
If you really need compatibility with POSIX sh, then you'll want to capture stdin to a file (at a potentially very large cost to efficiency):
#!/bin/sh
# create a temporary file
tempfile=$(mktemp "${TMPDIR:-/tmp}/input.XXXXXX") || exit
# capture all of stdin to that temporary file
cat >"$tempfile"
# nohup a process that reads from that temporary file
tempfile="$tempfile" nohup sh -c 'prog <"$tempfile"; rm -f "$tempfile"' &
nohup
-- it does nothing the shell can't do on its own. Seedisown
/bin/sh
but tagging the question bash.sh
specifies POSIX sh, not bash -- does the tag mean a bash-only answer is acceptable?sh
andbash
.sh
, notbash
.nohup
closes stdin (behavior you don't want), anddisown
is a non-POSIX extension.