Let's say that we invoke the nohup
in the following way:
nohup foo.py -n 20 2>&1 &
This will write the output to the nohup.out
.
How could we achieve to have the whole command nohup foo.py -n 20 2>&1 &
sitting at the top of the nohup.out
(or any other specified output file) after which the regular output of the executed command will be written to that file?
The reason for this is for purely debugging purpose as there will be thousands of commands like this executed and very often some of them will crash due to various reasons. It's like a basic report kept in a file with the executed command written at the top followed by the output of the executed command.
CodePudding user response:
A straightforward alternative would be something like:
myNohup() {
(
set m # disable job control
[[ -t 0 ]] && exec </dev/null # redirect stdin away from tty
[[ -t 1 ]] && exec >nohup.out # redirect stdout away from tty
[[ -t 2 ]] && exec 2>&1 # redirect stderr away from tty
set -x # enable trace logging of all commands run
"$@" # run our arguments as a command
) & disown -h "$!" # do not forward any HUP signal to the child process
}
To define a command we can test this with:
waitAndWrite() { sleep 5; echo "finished"; }
...and run:
myNohup waitAndWrite
...will return immediately and, after five seconds, leave the following in nohup.out
:
waitAndWrite
sleep 5
echo finished
finished
If you only want to write the exact command run without the side effects of xtrace, replace the set -x
with (assuming bash 5.0 or newer) printf '%s\n' "${*@Q}"
.
For older versions of bash, you might instead consider printf '%q ' "$@"; printf '\n'
.
This does differ a little from what the question proposes:
- Redirections and other shell directives are not logged by
set -x
. When you runnohup foo 2>&1 &
, the2>&1
is not passed as an argument tonohup
; instead, it's something the shell does beforenohup
is started. Similarly, the&
is not an argument but an instruction to the shell not towait()
for the subprocess to finish before going on to future commands.