bash 在 Mac 终端中暂停正在运行的脚本,然后再继续

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20649783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:32:55  来源:igfitidea点击:

Pause a running script in Mac terminal and then resume later

macosbashterminal

提问by Jikku Jose

How can I pause (not stop) a running script from Terminal in OSX, to resume it later from the point it paused?

如何从 OSX 中的终端暂停(而不是停止)正在运行的脚本,以便稍后从暂停点恢复它?

采纳答案by mklement0

To complement @devnull and @DavidW's helpful answers:
Here are convenience functions for suspending (pausing) / resuming a script by name, from anyshell (not just the one that started the script):

补充@devnull 和@DavidW 的有用答案:
以下是从任何shell(不仅仅是启动脚本的shell )按名称暂停(暂停)/恢复脚本的便利函数

Pass the script's filename(s) (withoutpath):

传递脚本的文件名(不带路径):

suspend-script someScript ...

suspend-script someScript ...

and later:

然后:

resume-script someScript ...

resume-script someScript ...

Update: Added additional function for killinga script by name: kill-script someScript ...

更新:添加了按名称杀死脚本的附加功能:kill-script someScript ...

  • Works with scripts run by either bashor sh(which is effectively just a bashalias 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-scriptand resume-script: if a script process is already in the desired state, no operation is performed (and no error is reported).
  • 适用于由bashor运行的脚本sh(这实际上只是bashOSX 上的别名)。
  • 如果一个脚本的多个实例正在运行,则只针对最近启动的实例。
  • 如果失败(包括未找到指定名称的正在运行的脚本),退出代码将为非零。
  • suspend-scriptresume-script:如果脚本进程已经处于所需状态,则不执行任何操作(并且不报告错误)。

Functions (e.g., place them in ~/.bash_profile):

函数(例如,将它们放在 中~/.bash_profile):

suspend-script() {
  [[ -z  ||  == '-h' ||  == '--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 "'' suspended." \
      || { ec=$?; echo "ERROR: bash/sh script process not found: '$p'" 1>&2; }
  done
  return $ec
}

resume-script() {
  [[ -z  ||  == '-h' ||  == '--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 "'' resumed." \
     || { ec=$?; echo "ERROR: bash/sh script process not found: '$p'" 1>&2; }
  done
  return $ec
}

kill-script() {
  [[ -z  ||  == '-h' ||  == '--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 "'' killed." \
     || { ec=$?; echo "ERROR: bash/sh script process not found: '$p'" 1>&2; }
  done
  return $ec
}

回答by David W.

If you're using BASH as the shell (which is the default shell on a Mac), you can use BASH's built in job controlcapabilities.

如果您使用 BASH 作为 shell(这是 Mac 上的默认 shell),您可以使用 BASH 的内置作业控制功能。

If the script is running in the foreground of your terminal, you can press Control-Zto pause the script. This will suspendthe running of the script.

如果脚本在终端的前台运行,您可以按Control-Z暂停脚本。这将暂停脚本的运行。

To restart it, type jobsand you'll see the suspended joblisted there. Type fgor more specific fg %xwhere xis the number of the suspended job.

要重新启动它,请键入jobs,您将看到此处列出了挂起的作业。键入fg或更具体的fg %x位置x是暂停作业的编号。

$ 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-Zkey that suspends the job is the default, but could be modified. The sttycan change this and will show you the current default:

暂停作业的Control-Z键是默认的,但可以修改。该stty的可以改变这一点,会告诉你当前的默认:

$ 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 suspendyour script. In this case, it's Control-Z.

你可以看到最后一行有susp = ^Z. 这是暂停脚本的关键。在这种情况下,它是Control-Z

You can also use the bgcommand to make a suspended jobrun in the background. However, that background job will terminate when you close the shell/Terminal Window unless you had prepended nohupto the front of the command.

您还可以使用该bg命令使暂停的作业在后台运行。但是,除非您在命令前面添加了nohup,否则当您关闭 shell/终端窗口时,后台作业将终止。

回答by devnull

Find the process ID of the running script.

查找正在运行的脚本的进程 ID。

To stop (or what you refer to as pause) the script, say:

要停止(或您所说的pause)脚本,请说:

kill -SIGSTOP PID

To resume the stopped (or paused) process, say:

要恢复停止(或暂停)进程,请说:

kill -SIGCONT PID

(where PIDrefers to the numeric process ID.)

(其中PID指的是数字进程 ID。)

回答by MayTheSForceBeWithYou

echo Press any key to continue... read blah

echo Press any key to continue... read blah

Then just don't do anything with the variable. This is as close to the pausefunctionality that I've used in DOS batch scripts that I've come across.

然后不要对变量做任何事情。这与pause我在 DOS 批处理脚本中使用的功能非常接近。