Ctrl-C与bash中的两个同时命令


15

我想在Linux机器上的bash中同时运行两个命令。因此,在我的./execute.shbash脚本中,我输入:

command 1 & command 2
echo "done"

但是,当我想停止bash脚本并按Ctrl+时C,仅第二个命令停止。第一个命令保持运行。如何确保完整的bash脚本已停止?或者在任何情况下,如何停止两个命令?因为在这种情况下,无论我多按一次Ctrl+ C,命令都会继续运行,并且我不得不关闭终端。


将后续问题变成一个单独的问题,然后在此处删除。现在不清楚访客是否回答了两个问题,还是只是最初的问题。
塞尔达2014年

Answers:


17

如果您输入

command 1 & command 2

这等于

command 1 &
command 2

即这将在后台运行第一个命令,然后在前台运行第二个命令。尤其是,这意味着即使您仍在运行,也要echo "done"command 2完成打印后进行打印command 1

你可能想要

command 1 &
command 2 &
wait
echo "done"

这将在后台运行两个命令,并等待两个命令完成。


如果按CTRL-C,则只会将SIGINT信号发送到前台进程,即command 2您的版本或wait我的版本。

我建议设置这样的陷阱:

#!/bin/bash

trap killgroup SIGINT

killgroup(){
  echo killing...
  kill 0
}

loop(){
  echo $1
  sleep $1
  loop $1
}

loop 1 &
loop 2 &
wait

使用陷阱可以捕获CTRL-C产生的SIGINT信号,并替换为该killgroup函数,该函数将杀死所有这些进程。


谢谢您的回答!但是,我确实有一个后续问题。我现在有以下脚本:trap killgroup SIGINT killgroup(){echo killing ... kill 0} command001 command1&command2我省略了wait命令,因为当command2完成时允许脚本继续执行。但是,当我运行脚本时,似乎命令1已经启动。我可以解决这个问题吗?谢谢
maero21

command1完成后,command1将立即启动。您可以set -x在脚本开头使用来打印执行的命令。
michas,2014年

6

从脚本将命令置于后台时,PID不会显示在屏幕上。您可以使用$!存储最后一个进程的PID 的内置变量,以便捕获command1的PID。

command1 &
echo $!

将回显command1的PID。

Bash还提供了内置的陷阱,您可以使用该陷阱注册接收特定信号时要运行的命令序列。您可以使用它在退出主脚本之前捕获SIGINT并杀死command1,例如

#!/bin/bash

onINT() {
echo "Killing command1 $command1PID too"
kill -INT "$command1PID"
exit
}

trap "onINT" SIGINT
command1 &
command1PID="$!"
comamnd2
echo Done

现在,在运行命令2的同时,点击Ctrl C将导致同时向command1和command2发送SIGINT。


您还可以使用%n语法杀死该Shell中的特定后台作业。通常,您发出kill %1命令杀死最新的且唯一的后台进程。如果有更多后台进程,jobs请先查看列表。
9000

@ 9000:是的,但是OP在脚本(./execute.sh)中运行命令,因此确保作业正常工作会成问题吗?

@lain:当然。我错过了从脚本运行的要点。
9000


1

Ctrl+ C将SIGINT信号发送到您的前端进程,即command2command1在后台运行,因此不受输入流的影响。

当您键入时command1 &,bash应该为您提供进程的PID,例如[1234]。要终止此过程,可以使用kill 1234。现在,如果你同时拥有的PID command1command2(看看ps -ef),你可以使用kill终止所有这些:

kill pid1 pid2 pid3 ...

一个小技巧是在后台运行两个命令:

command1 & command2 &

Bash会给你两个PID,准备被杀死。另一个诀窍是command1一旦您杀死了,就让自己回到前台command2

command1 & command2
# Hit Ctrl+C : command2 terminates.

fg # Bring back command1 to foreground.
# Hit Ctrl+C again, command1 terminates.

可在此处获取更多信息:http : //linuxg.net/how-to-manage-background-and-foreground-processes/

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.