Is there a way to redirect the nohup output to the stdin instead of nohup.out ?
I've tried:
nohup echo Hello > /dev/stdin 2>&1 &
But it does not the trick.
The nohup command purposefully detaches itself from the stdin, so there is nothing it expects to read in itself, and thus I think what you are really after in this question, is redirecting the output of nohup as the stdin for the next command. (Well somebody has to read the stdin, and it ain't nohup.)
Further, POSIX mandates that the output goes to the nohup.out file in the working directory, if the file can be successfully opened. So what you can do is to wire the stdin of the following commands from the nohup.out file. For instance:
$ nohup echo Hello 2>/dev/null; read VAR 0<nohup.out; echo "VAR=$VAR"
VAR=Hello
Related
I want to redirect stderr and stdout to a file inside my bash script myscript.sh where some sub-processes are run.
The easiest way is to write a wrapper script start_myscript.sh that calls myscript.sh 2>&1 > logfile or myscript.sh &> logfile.
I wonder if it is possible to redirect both stderr and stdout inside myscript.sh to a logfile without using a wrapper script?
Fot this I opened a new file descriptor 3 and redirected stderr and stdout to fd3 which I redirect to /tmp/logfile.
#!/bin/bash
exec 3> /tmp/logfile
exec 1>&3
exec 2>&3
doing_something &
doing_other_things &
Both functions are doing something and producing output to stderr or stdout. The thing is they are working simultaneously and sometimes writing at the same time to stdout/stderr.
In this case a sentence from the first function is interrupted, then follows an output from the second one and finally follows the last part of the sentence from the first function. That breaks any log file...
So I thought of FIFO named pipes as it should be blocking and did a short test:
#!/bin/bash
PIPE=/tmp/mypipe
mkfifo $PIPE
cat LONGTEXTFILE > $PIPE &
ls -la /usr/bin > $PIPE &
ls -la /tmp > $PIPE &
The test is simple. I create a named pipe $PIPE, cat a long text file over some seconds to stdout which is redirected to the named pipe. I'm doing this in the background while short calls of ls redirect its output to the named pipe. This should simulate output from different functions running at once in the background.
In another terminal I opened the named pipe with
cat /tmp/mypipe
My assumption was that the FIFO named pipe is blocked while it gets input from cat and stdout from ls would wait until stdout from cat ends.
Unfortunately the result is disappointing. Output from ls is placed somewhere in the middle of the output from cat, not afterwards.
Have I done any mistakes?
Is there any other way to redirect stderr/stdout from inside a script to a logfile without using a wrapper script?
I have a program prog that takes stdin input like this:
prog < test.txt
But the processing takes quite a lot time, so once the input is read, it the process should background.
From this answer https://unix.stackexchange.com/a/71218/201221 I have working solution, but without nohup. How modify it to use nohup too?
#!/bin/sh
{ prog <&3 3<&- & } 3<&0
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"' &
From what I see the following code is contained in a separate shell file:
#!/bin/sh
{ prog <&3 3<&- & } 3<&0
So, why not try just:
nohup the_file.sh &
When I'm running command nohup sh script.sh & in Terminal I have the following output:
[1] 42603
appending output to nohup.out. Where 42603 is process id of this command, but I don't want to see it. What can I do?
P.S. I'm running OSX Capitan, version 10.11.6
You can run nohup in a subshell and redirect the subshell's output to /dev/null like this: (nohup sh script.sh &) >/dev/null (note that this will also hide any output from sh script.sh)
something like this will mute that one line and will keep the script.sh connected to stdout
nohup sh script.sh & | grep -v nohup.out
if it is outputting that thing to stderr you will need to redirect to stdout
nohup sh script.sh 2>&1 & | grep -v nohup.out maybe the order is wrong there, my shell scripting syntax is usually wrong
Nohup redirects stderr to stdout if it points to a terminal. But I want to retain stderr output to the terminal
Is there a way to accomplish that? Is there an alternative?
I don't know if I understood correctly or not.
you mean that you don't want to see the error in terminal?
if yes:
if you want to save the error in file:
nohup command 2> file.txt
if you don't need the errors:
nohup command 2> /dev/null
2 means the error output of command
2> file.txt means write the error output to the file.txt
Just redirect it somewhere else, so it's not the terminal:
nohup bash -c 'echo OUT ; echo ERR >& 2' 2> err
You can redirect the stderr back to stdout instead of to a file to keep the output in the terminal, but it doesn't make much sense: nohup is for situations where the terminal might get lost, in which case you'll lose the stderr.
nohup bash -c 'echo OUT ; echo ERR >& 2' 2> >(cat)
Here is my script (run.sh):
rm -f nohup.out
nohup myproc &
tailf nohup.out
If I run the script (sh run.sh) then press Control-C, myproc will be terminated,
but if I comment the tailf nohup.out part, myproc will run on background as expected.
Am I doing anything wrong?
The problem is not SIGHUP (which nohup would catch) but SIGINT which you send by pressing Control-C. This is propagated to your process.
See this blog post for more details.
From what I read from that post you could change your code to something like this:
setsid myproc 1> output.log 2>&1 &
tail -f output.log
If you dont want to use your own output redirection, you can still use nohup:
setsid nohup ping -c 30 localhost &
tail -f nohup.out
Hope this helps!