Linux nohup process terminated when using tailf - linux

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!

Related

I want to output "<PID> Killed ~" to logfile when it kill -9 <PID>

I want to output this message /usr/local/ex1.sh: line xxx: <PID> Killed ex2.sh >> $LOG_FILE 2>&1 to logfile.
however
The "ex1.sh" output /usr/local/ex1.sh: line xxx: <PID> Killed ex2.sh >> $LOG_FILE 2>&1 to console when I executed ex1.sh in console.
The result that i want is that "ex1.sh" output to file, not that output to console.
This source is "ex1.sh".
ex2.sh >> $LOG_FILE 2>&1 &
PID=`ps -ef | grep ex2.sh | grep -v grep | gawk '{print $2}'`
/bin/kill -9 $PID >> $LOG_FILE 2>&1 &
Why does "ex1.sh" output this message to console?
The reason is that message '/usr/local/ex1.sh: line xxx: <PID> Killed ex2.sh >> $LOG_FILE 2>&1 is given by bash shell, not by kill command.
So if you redirect kill command output to a file, you will not get the message in the file.
If running like ./ex1.sh >> $LOG_FILE 2&>1, the message will be in the log file. Because ./ex1.sh forks a new bash process, the bash process will give out the message.
The output is in fact not written by the kill command or ex2.sh. It is written by the shell executing the background process ex2.sh.
The shell executing the script started the script ex2.sh in the background as a child process and is monitoring it. When the script is killed, the shell acts on this by printing the message.
In your special case the shell knows more about the killed process and the process executing kill. So it prints a rather verbose message.
If you start ex2.sh (without '&') in terminal 1 and kill it from terminal 2, the shell in terminal 1 will just print "Killed".

How to add nohup? - Redirect stdin to program and background

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 &

How to kill a process by reading from pid file using bash script in Jenkins?

Inside Jenkins, I have to run 2 separate scripts: start.sh and stop.sh. These scripts are inside my application which is fetched from a SCM . They are inside same directory.
The start.sh script runs a process in the background using nohup, and writes the processId to save_pid.pid. This script works fine. It successfully starts my application.
Then inside stop.sh, I am trying to read the processId from save_pid.pid to delete the process. But,I am unable to delete the process and the application keeps running until I kill the process manually using: sudo kill {processId}.
Here are the approaches that I have tried so far inside stop.sh but none of these work:
kill $(cat /path/to/save_pid.pid)
kill `cat /path/to/save_pid.pid`
kill -9 $(cat /path/to/save_pid.pid)
kill -9 `cat /path/to/save_pid.pid`
pkill -F /path/to/save_pid.pid
I have also tried all of these steps with sudo as well. But, it just doesn't work. I have kept an echo statement inside stop.sh, which prints and then there is nothing.
What am I doing wrong here ?
UPDATE:
The nohup command that I am using inside start.sh is something like this:
nohup deploy_script > $WORKSPACE/app.log 2>&1 & echo $! > $WORKSPACE/save_pid.pid
Please Note:
In my case, the value written inside save_pid.pid is surprisingly
always less by 1 than the value of actual processId. !!!
I think the reason why this happens is because you are not getting the PID of the process that you are interested in, but the PID of the shell executing your command.
Look:
$ echo "/bin/sleep 10" > /tmp/foo
$ chmod +x /tmp/foo
$ nohup /tmp/foo & echo $!
[1] 26787
26787
nohup: ignoring input and appending output to 'nohup.out'
$ pgrep sleep
26789
So 'nohup' will exec the 'shell', the 'shell' will fork a second 'shell' to exec 'sleep' in, however I can only count two processes here, so I am unable to account for one created PID.
Note that, if you put the nohup and the pgrep on one line, then pgrep will apparently be started faster than the shell that 'exec's 'sleep' and thus pgrep will yield nothing, which somewhat confirms my theory:
$ nohup /tmp/foo & echo $! ; pgrep sleep
[2] 26899
nohup: ignoring input and appending output to 'nohup.out'
$
If you launch your process directly, then nohup will "exec" your process and thus keep the same PID for the process as nohup itself had (see http://sources.debian.net/src/coreutils/8.23-4/src/nohup.c/#L225):
$ nohup /bin/sleep 10 & echo "$!"; pgrep sleep
[1] 27130
27130
nohup: ignoring input and appending output to 'nohup.out'
27130
Also, if you 'exec' 'sleep' inside the script, then there's only one process that's created (as expected):
$ echo "exec /bin/sleep 10" > /tmp/foo
$ nohup /tmp/foo & echo "$!"; pgrep sleep
[1] 27309
27309
nohup: ignoring input and appending output to 'nohup.out'
27309
Thus, according to my theory, if you'd 'exec' your process inside the script, then you'd be getting the correct PID.

Why nohup outputs process id?

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

How redirect nohup stdout to stdin

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

Resources