How can I 'pause' (not stop) a running script from terminal in OSX, to resume it later from the point it paused.
问题:
回答1:
To complement @devnull and @DavidW's helpful answers:
Here are convenience functions for suspending (pausing) / resuming a script by name, from any shell (not just the one that started the script):
Pass the script's filename(s) (without path):
suspend-script someScript ...
and later:
resume-script someScript ...
Update: Added additional function for killing a script by name: kill-script someScript ...
- Works with scripts run by either
bash
orsh
(which is effectively just abash
alias on OSX). - If multiple instances of a script are running, only the most recently started is targeted.
- Exit code will be non-zero in case of failure (including not finding a running script by the given name).
suspend-script
andresume-script
: if a script process is already in the desired state, no operation is performed (and no error is reported).
Functions (e.g., place them in ~/.bash_profile
):
suspend-script() { [[ -z $1 || $1 == '-h' || $1 == '--help' ]] && { echo "Usage: $FUNCNAME scriptFileName ..."$'\n'"Suspends the specified bash/sh script(s)."; return $(( ${#1} == 0 )); } local ec=0 for p in "$@"; do pkill -STOP -nf '/?(bash|sh)[ ]+(.*/)?'"$p"'( |$)' \ && echo "'$1' suspended." \ || { ec=$?; echo "ERROR: bash/sh script process not found: '$p'" 1>&2; } done return $ec } resume-script() { [[ -z $1 || $1 == '-h' || $1 == '--help' ]] && { echo "Usage: $FUNCNAME scriptFileName ..."$'\n'"Resumes the specified bash/sh script(s)."; return $(( ${#1} == 0 )); } local ec=0 for p in "$@"; do pkill -CONT -nf '/?(bash|sh)[ ]+(.*/)?'"$p"'( |$)' \ && echo "'$1' resumed." \ || { ec=$?; echo "ERROR: bash/sh script process not found: '$p'" 1>&2; } done return $ec } kill-script() { [[ -z $1 || $1 == '-h' || $1 == '--help' ]] && { echo "Usage: $FUNCNAME scriptFileName ..."$'\n'"Kills the specified bash/sh script(s)."; return $(( ${#1} == 0 )); } local ec=0 for p in "$@"; do pkill -nf '/?(bash|sh)[ ]+(.*/)?'"$p"'( |$)' \ && echo "'$1' killed." \ || { ec=$?; echo "ERROR: bash/sh script process not found: '$p'" 1>&2; } done return $ec }
回答2:
If you're using BASH as the shell (which is the default shell on a Mac), you can use BASH's built in job control capabilities.
If the script is running in the foreground of your terminal, you can press Control-Z to pause the script. This will suspend the running of the script.
To restart it, type jobs
and you'll see the suspended job listed there. Type fg
or more specific fg %x
where x
is the number of the suspended job.
$ test.pl # Test script (prints out Foo every two seconds Foo! Foo! ^Z $ # Job has been suspended $ jobs [1] + Stopped ./test.pl $ fg %1 #Restarts Job #1 Foo!
The Control-Z key that suspends the job is the default, but could be modified. The stty can change this and will show you the current default:
$ stty -a speed 9600 baud; 40 rows; 120 columns; lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo -extproc iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8 -ignbrk brkint -inpck -ignpar -parmrk oflags: opost onlcr -oxtabs -onocr -onlret cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow -dtrflow -mdmbuf cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>; eol2 = <undef>; erase = ^H; intr = ^C; kill = ^U; lnext = ^V; min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
You can see the very last line has susp = ^Z
. This is the key that will suspend your script. In this case, it's Control-Z.
You can also use the bg
command to make a suspended job run in the background. However, that background job will terminate when you close the shell/Terminal Window unless you had prepended nohup to the front of the command.
回答3:
Find the process ID of the running script.
To stop (or what you refer to as pause) the script, say:
kill -SIGSTOP PID
To resume the stopped (or paused) process, say:
kill -SIGCONT PID
(where PID
refers to the numeric process ID.)