如何在终端中停止循环bash脚本?


54

例如,

#!/bin/bash
while :
do
    sl
done

如何终止这个bash脚本?


1
给出更多细节。您要以交互方式还是通过编程方式停止它?
manatwork 2012年

1
您可以按ctrl-c以发送SIGINT信号(在大多数外壳中),也可以按ctrl-z以发送SIGTSTP信号(在大多数外壳中)。在您按下的情况下ctrl-z,相关进程不会被杀死,而是会暂停。您可以使用fg(至少在中bash)恢复它
user1146332 2012年

不,这不起作用!
Yinyanghu 2012年

4
问题不在于脚本,而是sl我认为对于那些拼写错误的人来说这是一个令人讨厌的命令ls,表明火车正在缓慢驶过。据我所知,它捕获了SIGINT信号,必须用杀死它SIGKILL

1
谢谢。没有为我的发行版打包,这就是为什么我不知道/发现它的原因。(我想我不会提出要求。)
manatwork 2012年

Answers:


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 2012年

120
  1. 按下Ctrl-Z以暂停脚本
  2. kill %%

%%讲述内置的bash kill要的信号(默认SIGTERM)发送到最近中止的后台任务在当前shell,而不是一个进程ID。

您也可以按编号或名称指定作业。例如,当您使用^ Z暂停作业时,bash会使用诸如告诉您其作业编号是什么[n]+ Stopped,其中n方括号内是作业编号。

有关作业控制和杀灭工作的详细信息,运行help jobshelp fghelp bg,和help kill在bash,和搜索JOB CONTROL(全部大写),或jobspec在bash的手册页。

例如

$ ./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
另一个好的答案!
Yinyanghu 2012年

2
顺便说一句,对于像这样的快速执行循环,^ Z是比^ C更可靠的杀死进程的方法。^ C将被发送到sl正在循环中运行的程序(),但脚本将继续运行...并启动另一个sl。如果确实快按几次^ C,则可能会同时杀死sl和和脚本(如果它们都不捕获SIGINT)。^ Z几乎会立即挂起脚本(如果您不计算仍在打印到终端的缓冲输出,则将立即挂起),因此可以使用kill %%
cas 2012年

究竟!我必须说“ sl是一个有趣的程序”。这次,再次让我开心!@ _ @
Yinyanghu 2012年

当不是从脚本而是直接从命令行调用循环时,只有答案似乎也起作用。
Skippy le Grand Gourou 2014年

1
@DrewChapin我不记得我何时/何地发现它-我一直都知道“永远”。bash手册页(搜索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”退出两个级别,依此类推。


加分1打破2
flyfinger

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杀死它。我只想知道如何直接杀死它!
Yinyanghu 2012年

3

最简单的方法是发出QUIT通常连接到的信号Control-Backslash

看到火车时,按Control- \


1

您可以kill使用pidshell(bash)。
我只是尝试了,而且效果很好。
因为我看不到过程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?
manatwork

-1

令人毛骨悚然的事情是可怕的,因为如果脚本必须运行两次,您现在就永远不会。并且您的退出代码是错误的。

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。同时打开自己的重击

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.