문제

I want to write a bash script that will continue to run if the user is disconnected, but can be aborted if the user presses Ctrl+C.

I can solve the first part of it like this:

#!/bin/bash
cmd='
#commands here, avoiding single quotes...
'
nohup bash -c "$cmd" &
tail -f nohup.out

But pressing Ctrl+C obviously just kills the tail process, not the main body. Can I have both? Maybe using Screen?

도움이 되었습니까?

해결책

I want to write a bash script that will continue to run if the user is disconnected, but can be aborted if the user presses Ctrl+C.

I think this is exactly the answer on the question you formulated, this one without screen:

#!/bin/bash
cmd=`cat <<EOF
# commands here
EOF
`
nohup bash -c "$cmd" &

# store the process id of the nohup process in a variable
CHPID=$!        

# whenever ctrl-c is pressed, kill the nohup process before exiting
trap "kill -9 $CHPID" INT

tail -f nohup.out

Note however that nohup is not reliable. When the invoking user logs out, chances are that nohup also quits immediately. In that case disown works better.

bash -c "$cmd" &
CHPID=$!
disown

다른 팁

This is probably the simplest form using screen:

screen -S SOMENAME script.sh

Then, if you get disconnected, on reconnection simply run:

screen -r SOMENAME

Ctrl+C should continue to work as expected

Fact 1: When a terminal (xterm for example) gets closed, the shell is supposed to send a SIGHUP ("hangup") to any processes running in it. This harkens back to the days of analog modems, when a program needed to clean up after itself if mom happened to pick up the phone while you were online. The signal could be trapped, so that a special function could do the cleanup (close files, remove temporary junk, etc). The concept of "losing your connection" still exists even though we use sockets and SSH tunnels instead of analog modems. (Concepts don't change; all that changes is the technology we use to implement them.)

Fact 2: The effect of Ctrl-C depends on your terminal settings. Normally, it will send a SIGINT, but you can check by running stty -a in your shell and looking for "intr".

You can use these facts to your advantage, using bash's trap command. For example try running this in a window, then press Ctrl-C and check the contents of /tmp/trapped. Then run it again, close the window, and again check the contents of /tmp/trapped:

#!/bin/bash

trap "echo 'one' > /tmp/trapped" 1
trap "echo 'two' > /tmp/trapped" 2

echo "Waiting..."
sleep 300000

For information on signals, you should be able to man signal (FreeBSD or OSX) or man 7 signal (Linux).

(For bonus points: See how I numbered my facts? Do you understand why?)

So ... to your question. To "survive" disconnection, you want to specify behaviour that will be run when your script traps SIGHUP.

(Bonus question #2: Now do you understand where nohup gets its name?)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top