web-dev-qa-db-ja.com

Mac端末で実行中のスクリプトを一時停止し、後で再開する

OSXのターミナルから実行中のスクリプトを一時停止(停止ではなく)して、一時停止したポイントから後で再開するにはどうすればよいですか?

20
Jikku Jose

@devnullと@DavidWの役立つ回答を補足するには:
これがスクリプトを一時停止(一時停止)/名前で再開するための便利な関数anyシェル(スクリプトを開始したものだけではありません):

スクリプトのファイル名を渡します(withoutpath):

suspend-script someScript ...

以降:

resume-script someScript ...

更新:スクリプトを名前でkillingするための追加関数を追加:kill-script someScript ...

  • bashまたはsh(事実上、OSXではbashエイリアス)によって実行されるスクリプトで動作します。
  • スクリプトの複数のインスタンスが実行されている場合、最後に開始されたもののみがターゲットになります。
  • 失敗した場合、終了コードはゼロ以外になります(指定された名前で実行中のスクリプトが見つからない場合を含む)。
  • suspend-scriptおよびresume-script:スクリプトプロセスがすでに目的の状態にある場合、操作は実行されません(エラーは報告されません)。

関数(例:~/.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
}
3
mklement0

シェルとしてBASH(Macのデフォルトのシェル)を使用している場合は、BASHの組み込みジョブ制御機能を使用できます。

スクリプトが端末のフォアグラウンドで実行されている場合は、 Control-Z スクリプトを一時停止します。これにより、スクリプトの実行がsuspendされます。

再起動するには、jobsと入力すると、中断されたjobがリストに表示されます。タイプ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!

ジョブを一時停止する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;

最後の行にsusp = ^Z。これは、スクリプトをsuspendするキーです。この場合、それはControl-Zです。

bgコマンドを使用して、中断されたjobをバックグラウンドで実行することもできます。ただし、コマンドの前に Nohup を付加していない限り、シェル/ターミナルウィンドウを閉じると、バックグラウンドジョブは終了します。

43
David W.

実行中のスクリプトのプロセスIDを見つけます。

スクリプト(またはpause)を停止するには、次のように言います。

kill -SIGSTOP PID

停止した(または一時停止)プロセスを再開するには、次のように言います。

kill -SIGCONT PID

PIDは数値のプロセスIDを指します。)

9
devnull

echo Press any key to continue... read blah

次に、変数に対して何もしないでください。これは、私が遭遇したDOSバッチスクリプトで使用したpause機能に近いものです。