在 bash 中使用两个同时命令的 Ctrl-C

mae*_*o21 17 shell signals process-management background-process

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

command 1 & command 2
echo "done"
Run Code Online (Sandbox Code Playgroud)

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

mic*_*has 19

如果你输入

command 1 & command 2
Run Code Online (Sandbox Code Playgroud)

这等于

command 1 &
command 2
Run Code Online (Sandbox Code Playgroud)

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

你可能想要

command 1 &
command 2 &
wait
echo "done"
Run Code Online (Sandbox Code Playgroud)

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


如果您按 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
Run Code Online (Sandbox Code Playgroud)

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


小智 7

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

command1 &
echo $!
Run Code Online (Sandbox Code Playgroud)

将回显 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
Run Code Online (Sandbox Code Playgroud)

现在,当命令 2 正在运行时,击中Ctrl C将导致命令 1和命令 2 都被发送 SIGINT。


Ole*_*nge 5

较新版本的 GNU Parallel 可以满足您的需求:

parallel ::: "command 1" "command 2"
echo "done"
Run Code Online (Sandbox Code Playgroud)

或者如果command保持不变:

parallel command ::: 1 2
echo done
Run Code Online (Sandbox Code Playgroud)

观看介绍视频以进行快速介绍:https : //www.youtube.com/playlist?list=PL284C9FF2488BC6D1

完成教程 (man parallel_tutorial)。你爱你的命令行。