bash - Redirect stdout/stderr of a background job from console to a log file?
2014-07
I just run a job (assume foo.sh).
./foo.sh
[Press Ctrl-Z to stop]
bg # enter background
And it generate output to stdout and stderr. Is there any method to redirect to stdout and stderr to other file instead of current screen?
Apparently I misread your question the first time, so here's my updated answer:
After you sent your program to the background, you first have to find its PID
pgrep foo.sh
Then you could use gdb
to attach to that process
gdb -p <PID>
In gdb
you then change where this program writes to
p dup2(open("/path/to/file",577, 420), 1)
p dup2(1, 2)
then you detach from the process and quit gdb
detach
quit
A little explanation
577
is equivalent toO_CREAT|O_WRONLY|O_TRUNC
420
is equivalent toS_IRUSR|S_IWUSR|S_IRGRP|S_IROTH
- So the call to
open
opens the file and truncates it to 0 bytes if it exists or creates a new one with the right file permissions if it doesn't exist - The first call to
dup2
duplicates the file descriptor returned by the call toopen
to file descriptor1
(which isstdout
) - The second call to
dup2
duplicates the file descriptor1
to2
(which isstderr
)
(1). Since background job can still run even if the user logs out, what's the point of using nohup and screen?
(2). What is the difference between CTRL+Z and stop to suspend a background job? There is another command "stop" which stops a background job. This doesn't kill the job, but it will not continue executing until it is restarted. I wonder what is the difference between "stop" and CTRL+Z? for "stop", see http://www.ece.osu.edu/computing/background_jobs.html#commands
(3). to make a background job noninteractive, is this correct?
command <<inputfile> ><outputfile>
What if I want to append the output to an existing file while keep the job background?
Thanks and regards!
Background jobs
Normal background jobs do not survive a termination of the parent shell:
pigpen ~: yes > /dev/null &
This will not survive a logout.
However, this will:
pigpen ~: nohup yes &
nohup
prevents the process from receiving a SIGHUP signal on logout.
Screen, on the other hand, maintains the illusion that the user is always logged in, and allows the user to reattach at any time. This has the advantage of being able to continue to interact with the program once reattached (impossible with nohup alone).
Ctrl+C
Ctrl+C sends a SIGINT to the process, which it may catch and ignore (uncommon).
I suggest reading the bash man page; specifically the sections on Signals and Job Control.
Ctrl+Z
You edited your question to use Ctrl+Z instead. Ctrl+Z sends a SIGTSTP signal to the process, suspending it. This process can be later continued by sending it a SIGCONT signal.
SIGTSTP signals can be caught by the program and ignored.
SIGSTP signal
The SIGSTP signal is different from SIGTSTP in that it cannot be caught by the running program. It's behavior is identical to the behavior of an uncaught SIGTSTP.
Resources
- Background jobs will only continue if you detach them (I believe), and you cannot get output or send input to them later. Screen will let you connect to it later, as though you never left it.
- Control+c is a keyboard interrupt, all it does is send a signal to the running program, which will normally respond by exiting, but it not forced to. Stopping it will send a different signal, where the application will generally stop what it's doing until it gets a continue signal (this can be done with control+z).
- the background job will die if you exit the shell you started it in. (eg SSH), that's why you use nohup or screen. If you have modern bash shell, there's a disown -h command. see man page of bash for more info
- Ctrl-C and suspend are different. Ctrl-C terminates the process.
- To append output to existing file :
1>>/path/existing_file
- ctrl-Z suspend the process, bring it into the background and give the control back to you. I don't know the exact meaning of your "stop"
- To append output and put in background:
command 1>>/path/existing_file &