ターミナルでループbashスクリプトを停止する方法は?


54

例えば、

#!/bin/bash
while :
do
    sl
done

このbashスクリプトを終了する方法は?


1
詳細を入力してください。インタラクティブまたはプログラムで停止しますか?
マナトワーク

1
あなたは押すことができますctrl-c送信するためにSIGINT(ほとんどのシェルで)信号を、またはあなたが押すことができますctrl-zそれが送信SIGTSTP(ほとんどのシェルで)信号を出力します。押した場合ctrl-z、関連するプロセスは強制終了されず、一時停止されます。fg(少なくともbash)で再開できます
-user1146332

いいえ、機能しません!
陰陽湖

4
問題はスクリプトではなく、slスペルを間違えた人にとっては迷惑なコマンドlsであり、電車がゆっくりと通り過ぎることを示すコマンドだと考えています。私が知る限り、それはSIGINTシグナルをトラップし、で殺されなければなりませんSIGKILL

1
ありがとう。私のディストリビューションに詰め込まれていないので、私はそれを知らなかった/見つけなかったのです。(私はそれの要求を提出しないと思います。)
manatwork

回答:


64

プログラムはをsl意図的に無視しSIGINTますCtrl+C。そのため、まず、引数を追加slして無視SIGINTしないように指示する必要があり-eます。

これを試してみると、各個人を停止できることに気づくでしょうslが、それでも繰り返します。同様bashに終了するように指示する必要がありSIGINTます。これを行うtrap "exit" INTには、ループの前にaを置きます。

#!/bin/bash
trap "exit" INT
while :
do
    sl -e
done

5
私はそれをチェックするためにインストールされていませんが、またのCtrl- \からSIGQUITでそれを殺すことができるかもしれない
derobert

120
  1. を押しCtrl-Zてスクリプトを一時停止します
  2. kill %%

これ%%は、killプロセスIDではなく、現在のシェルで最後に中断されたバックグラウンドジョブにシグナル(デフォルトではSIGTERM)を送信することをbashビルトインに通知します。

ジョブを番号または名前で指定することもできます。あなたが^ Zでジョブを中断するときなどには、bashはそのジョブ番号のようなものであるかを教えてくれる[n]+ Stoppedn角括弧内はジョブ番号です。

ジョブ実行制御のと殺すのジョブの詳細情報についてはhelp jobshelp fghelp bg、およびhelp killbashで、及びで検索JOB CONTROL(すべて大文字)またはjobspec、bashのmanページで。

例えば

$ ./killme.sh 
./killme.sh:行4:sl:コマンドが見つかりません
./killme.sh:行4:sl:コマンドが見つかりません
./killme.sh:行4:sl:コマンドが見つかりません
./killme.sh:行4:sl:コマンドが見つかりません
./killme.sh:行4:sl:コマンドが見つかりません
...
...
...
./killme.sh:行4:sl:コマンドが見つかりません
^ Z
[1] +停止./killme.sh
$キル%%
$ 
[1] +終了./killme.sh

この例では、ジョブの番号は1だったのでkill %1、同じように機能していましたkill %%

(注:slインストールしていないので、出力は「コマンドが見つかりません」です。あなたの場合、slが生成する出力が得られます。重要ではありません- ^Zサスペンドとkill %%同じように動作します)


3
別の良い答え!
陰陽湖

2
ところで、このようなループを迅速に実行するために、^ Zは^ Cよりもプロセスを強制終了するより信頼できる方法です。^ Cはslループで実行されているプログラム()に送信されますが、スクリプトは実行を続け、別のスクリプトを開始しslます。^ Cを数回非常に高速に押すslと、スクリプトとスクリプトの両方を強制終了できます(どちらもSIGINTをトラップしない場合)。^(あなたはまだあなたの端末に印刷されているバッファリングされた出力をカウントしない場合は、すぐに)Zは、ほとんどすぐにスクリプトを一時停止しますので、あなたがそれを殺すことができますkill %%
CAS

まさに!「sl楽しいプログラムです」と言わなければなりません。今回はまた楽しいです!@ _ @
陰陽湖

ループがスクリプトからではなく、コマンドラインから直接呼び出された場合にも機能すると思われる回答のみ。
スキッピールグラングロウ14

1
@DrewChapin私はそれをいつ/どこで見つけたのか思い出せません-「永遠に」から知っていることです。bashのmanページ(のための検索のjobspecは)言う:The symbols %% and %+ refer to the shell's notion of the current job, which is the last job stopped while it was in the foreground or started in the background. The previous job may be referenced using %-. If there is only a single job, %+ and %- can both be used to refer to that job
CAS

6

ctrl + cでループを停止したいが、スクリプトを終了したくない|| break場合は、実行中のコマンドの後に配置できます。実行中のプログラムがctrl + cで終了する限り、これはうまく機能します。

#!/bin/bash
while :
do
    # ctrl+c terminates sl, but not the shell script
    sl -e || break
done

ネストされたループにいる場合は、「break 2」を使用して2つのレベルから抜け出すことができます。


休憩2にプラス1
flyingfinger

3

このスクリプトを開始した端末でCtrl + Cを押すと、そのスクリプトを終了できます。もちろん、このスクリプトはフォアグラウンドで実行する必要があるため、Ctrl + Cで停止できます。

または、次の方法で、開いている他のターミナルでそのスクリプトのPID(プロセスID)を見つけることができます。

ps -ef | grep <name_of_the_script>
kill -9 <pid_of_your_running_script>

どちらの方法でも、求めているトリックを実行する必要があります。


1
端末からCtrl + Cで終了することはできません。だから私はpsまたはtopでそれを殺さなければなりません。私はそれを直接殺す方法を知りたいだけです!
陰陽湖

3

最も簡単な方法はQUIT、通常はに接続されている信号を発行することControl-Backslashです。

列車が表示されたら、Control- \を押します


1

することができますシェルの(bashの)。 試したところうまくいきました。 プロセス(ループスクリプトで実行するジョブ)が表示されないためです。killpid

ps -ef


0

スクリプト全体を終了する別の方法は、slコマンドをバックグラウンドにしてからsignal INTをトラップして、signalでスクリプトのプロセスグループ全体を強制終了することHUPです。

#!/bin/bash

trap 'trap - INT; kill -s HUP -- -$$' INT
#trap 'trap - INT; kill -s HUP 0' INT

while :
do
   sl & wait
done


-1
while [ true ] 
do

  #check if script is running
  ps | grep script_name.sh | grep -v grep >/dev/null 2>&1

  if [ "$!" != "0" ] ; then
    break
  else

    kill -9 ` ps -ef | grep script_name.sh | cut -d "a" -f 1` 
    echo "kill -9 `get script PID`"

  fi

done

これが役立つはずです。


2
最後のバックグラウンドコマンドのPIDが0になるのはなぜだと思いますか?
マナトワーク

-1

スクリプトを2回実行する必要がある場合、今は絶対にしないため、殺害はひどいものです。そして、終了コードが間違っています。

while [ something ]; do

 if [ somethingelse ]; then
   echo shut down script with exit code 0
   exit 0
 fi
done

echo something else not happend
exit 2 # Return val important for example for monitoring

動作しません。解決策= perlを使用します。自分のbashを開きながら

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.