How to prevent a background process from being stopped after closing SSH client in Linux

236,187

Solution 1

Check out the "nohup" program.

Solution 2

I would recommend using GNU Screen. It allows you to disconnect from the server while all of your processes continue to run. I don't know how I lived without it before I knew it existed.

Solution 3

When the session is closed the process receives the SIGHUP signal which it is apparently not catching. You can use the nohup command when launching the process or the bash built-in command disown -h after starting the process to prevent this from happening:

> help disown
disown: disown [-h] [-ar] [jobspec ...]
     By default, removes each JOBSPEC argument from the table of active jobs.
    If the -h option is given, the job is not removed from the table, but is
    marked so that SIGHUP is not sent to the job if the shell receives a
    SIGHUP.  The -a option, when JOBSPEC is not supplied, means to remove all
    jobs from the job table; the -r option means to remove only running jobs.

Solution 4

daemonize? nohup? SCREEN? (tmux ftw, screen is junk ;-)

Just do what every other app has done since the beginning -- double fork.

# ((exec sleep 30)&)
# grep PPid /proc/`pgrep sleep`/status
PPid:   1
# jobs
# disown
bash: disown: current: no such job

Bang! Done :-) I've used this countless times on all types of apps and many old machines. You can combine with redirects and whatnot to open a private channel between you and the process.

Create as coproc.sh:

#!/bin/bash

IFS=

run_in_coproc () {
    echo "coproc[$1] -> main"
    read -r; echo $REPLY
}

# dynamic-coprocess-generator. nice.
_coproc () {
    local i o e n=${1//[^A-Za-z0-9_]}; shift
    exec {i}<> <(:) {o}<> >(:) {e}<> >(:)
. /dev/stdin <<COPROC "${@}"
    (("\$@")&) <&$i >&$o 2>&$e
    $n=( $o $i $e )
COPROC
}

# pi-rads-of-awesome?
for x in {0..5}; do
    _coproc COPROC$x run_in_coproc $x
    declare -p COPROC$x
done

for x in COPROC{0..5}; do
. /dev/stdin <<RUN
    read -r -u \${$x[0]}; echo \$REPLY
    echo "$x <- main" >&\${$x[1]}
    read -r -u \${$x[0]}; echo \$REPLY
RUN
done

and then

# ./coproc.sh 
declare -a COPROC0='([0]="21" [1]="16" [2]="23")'
declare -a COPROC1='([0]="24" [1]="19" [2]="26")'
declare -a COPROC2='([0]="27" [1]="22" [2]="29")'
declare -a COPROC3='([0]="30" [1]="25" [2]="32")'
declare -a COPROC4='([0]="33" [1]="28" [2]="35")'
declare -a COPROC5='([0]="36" [1]="31" [2]="38")'
coproc[0] -> main
COPROC0 <- main
coproc[1] -> main
COPROC1 <- main
coproc[2] -> main
COPROC2 <- main
coproc[3] -> main
COPROC3 <- main
coproc[4] -> main
COPROC4 <- main
coproc[5] -> main
COPROC5 <- main

And there you go, spawn whatever. the <(:) opens an anonymous pipe via process substitution, which dies, but the pipe sticks around because you have a handle to it. I usually do a sleep 1 instead of : because its slightly racy, and I'd get a "file busy" error -- never happens if a real command is ran (eg, command true)

"heredoc sourcing":

. /dev/stdin <<EOF
[...]
EOF

This works on every single shell I've ever tried, including busybox/etc (initramfs). I've never seen it done before, I independently discovered it while prodding, who knew source could accept args? But it often serves as a much more manageable form of eval, if there is such a thing.

Solution 5

nohup blah &

Substitute your process name for blah!

Share:
236,187

Related videos on Youtube

Berkyjay
Author by

Berkyjay

Updated on October 18, 2020

Comments

  • Berkyjay
    Berkyjay over 3 years

    I'm working on a Linux machine through SSH (Putty). I need to leave a process running during the night, so I thought I could do that by starting the process in background (with an ampersand at the end of the command) and redirecting stdout to a file.

    To my surprise, that doesn't work. As soon as I close the Putty window, the process is stopped.

    How can I prevent that from happening??

  • David Nehme
    David Nehme over 15 years
    you might want to add redirect standard out and standard error.
  • user3532201
    user3532201 over 15 years
    This is one of the greatest pieces of software I've ever used. Seriously. I have it running on a BSD box that I ssh into from EVERYWHERE, and can simply re-attach to my screen and have all of my terminals where I'm doing all sorts of stuff.
  • willasaywhat
    willasaywhat over 15 years
    I can attest to this one. Screen is a great application. The ability to re-attach is amazing, and saves a lot of potentially lost work.
  • user3532201
    user3532201 over 15 years
    I even use it on local machines, and attach multiple xterms to the same screen session (screen -x). That way I can open up many windows within my screen session, and freely switch my various xterms from window-to-window.
  • Jonas Engström
    Jonas Engström over 15 years
    screen is definately on my top 3 too, truly awesome software.
  • Lawrence Hutton
    Lawrence Hutton over 15 years
    Depends on whether you need to reconnect to the backgrounded app or not. If you do, then, yeah, screen is the only way to fly. If it's fire-and-forget, though, then nohup fits the bill just as nicely, if not better.
  • Josh
    Josh about 15 years
    There is also 'dtach' which implements only screen's detach mechanism, however it's a bit harder to use but gives control over the socket file that gets created for a detached process. I would recommend using dtach if this were a non-interactive scripted process that needed to remotely launch processes. Otherwise just use screen, it's easier.
  • Chas. Owens
    Chas. Owens about 15 years
    nohup redirects stdout and stderr to nohup.out (or nohup.out and nohup.err depending on the version), so unless you are running multiple commands it is not necessary.
  • Rob
    Rob over 14 years
    Why don't you put the source on github or bitbucket?
  • Jonathan Leffler
    Jonathan Leffler over 14 years
    Why does the absence of the source from github warrant a downvote?
  • Aman Jain
    Aman Jain over 14 years
    yeah, screen is awesome, its like a non-gui vnc session :)
  • Derek Dahmer
    Derek Dahmer almost 14 years
    How do you stop it afterwards?
  • JesperE
    JesperE almost 14 years
    Log in and do "kill <pid>". Use "pidof" if you don't know the pid.
  • anthonyrisinger
    anthonyrisinger about 12 years
    why the down vote ... so what if the question is old; it's obviously relevant considering there are 11 other answers that suck. this solutions is, sans systemd, the idiomatic and accepted way to daemonize for the last 30 years, not pointless apps, eg. nohup et al.
  • THESorcerer
    THESorcerer almost 12 years
    PS anthonyrisinger, you are good, i give you that but ... 30 years ? i bet that is a solution when &, bg, nohup or screen was not there yet, and no offense i appreciate your knowledge but that is far too complicated to use it :)
  • Christian K.
    Christian K. almost 12 years
    Advantage here is that disown works for processes which have already been started.
  • anthonyrisinger
    anthonyrisinger over 11 years
    (aside: see Tmux) although this vastly predates me [1987], & (asynchronous execution) was introduced by the Thompson shell in 1971, for the first version of UNIX ... so it literally "has always been" ;-) alas, I was too conservative -- it's actually been 41 years.
  • Alex D
    Alex D over 11 years
    no matter how good your answer is, sometimes somebody on SO won't like it and will downvote. It's better not to worry about it too much.
  • KCD
    KCD about 11 years
    You can use nohup command > /dev/null 2>&1 & to run in the background without creating any stdout or stderr output (no nohup.out file)
  • Stewart
    Stewart almost 11 years
    Does 'jobspec' mean the pid?
  • Stewart
    Stewart almost 11 years
    No worries, found this answer here stackoverflow.com/questions/625409/…
  • tbc0
    tbc0 almost 11 years
    This technique doesn't work when trying to start a job programmatically via ssh, e.g. '$ ssh myhost "((exec sleep 30)&)"'
  • anthonyrisinger
    anthonyrisinger over 10 years
    @tbc0 sure it does; Ctrl^C the ssh client after it hangs then login to the machine... you will find the sleep 30 command is still running. i'm not sure off-hand why ssh does not release (though i'd guess the sleep process still holds a ref to ssh's pty or similar) but regardless, the sleep command is unaffected by any signals sent (such as the Ctrl^C) and will persist after ssh closes.
  • anthonyrisinger
    anthonyrisinger over 10 years
    @tbc0 ...try ssh myhost "((exec sleep 500)&) >/dev/null"
  • tbc0
    tbc0 over 10 years
    @anthonyrisinger ok, that works. I think this is cleaner: ssh myhost 'sleep 500 >&- 2>&- <&- &' TMTOWTDI ;)
  • Sergey
    Sergey over 10 years
    What if I need to provide some input? For example, I have a long-running script that I need to run in the background but it first asks for my FTP password. nohup doesn't help in this case. Is there a way to fiddle with Ctrl+Z / bg?
  • gerlos
    gerlos about 10 years
    +1 for screen. Or, as an alternative, tmux (I like this one more than screen) or even byobu, which is a nice frontend for screen or tmux. You can just type screen to get a shell to use and return later at any time, or run your command with screen, like "screen command": the screen session will exist as long as the process "command" exist, and if it's something very long, you can go back and look at its standard output at any time.
  • Anomaly
    Anomaly over 8 years
    Since I'm lazy and bad at memorizing cryptic sequences of characters, I wrote this, based on what @KCD said, and have been using it a lot.
  • tymik
    tymik almost 8 years
    assuming that yum is the right tool, when you don't know the distro, is not good. you should make it clear on which distros screen can be installed with yum.
  • Hamy
    Hamy over 7 years
    This is great. the only solution that actually works in busybox. it deserves more upvotes
  • Berkyjay
    Berkyjay over 7 years
    Can this be used to run binary executables?
  • haccks
    haccks over 7 years
    @GetFree; Yes. You can.
  • Berkyjay
    Berkyjay over 7 years
    Add an example please. The answer as it is right now looks like it's good only for script files.
  • haccks
    haccks over 7 years
    @GetFree; Added the example. Let me know if you have any problem.
  • DepressedDaniel
    DepressedDaniel about 7 years
    @JonathanLeffler IMHO listing all the cool options of a program that is not publicly available in any form (not even commercially) borders on wasting the reader's time.
  • Tino
    Tino about 7 years
    This does not work at my side as this does not shield the program from getting SIGHUP when the ctty is closed. I have a program which must not receive SIGHUP, ever. nohup does not work, as it does not prevent SIGHUP, it just defaults to ignore it, which need not prevail. As I do not have screen nor tmux nor at nor similar, I need a way on shell level to disassociate a program from the ctty for sure. The only way I found was a hack to start the program with ssh -T remote '(program&)&' which makes it impossible to background the program in an interactive ssh session.
  • mabalenk
    mabalenk about 7 years
    Linode website offers a good introduction on how to use screen.
  • kilgoretrout
    kilgoretrout over 5 years
    this is the way to go