有没有办法只终止命令序列中的第一个命令?

Is there a way to terminate only the first command in a sequence of commands?

使用 tmux 时,我使用等待功能,在命令完成后 tmux 会话会收到通知。但是有时我想终止命令序列而不终止等待部分,这样原始脚本就不会挂起。

基本上,如果我有:

command 1; command 2

在我主要想退出命令 1 但继续执行命令 2(这是等待确认,因此脚本不会挂起)的地方,按 Ctrl-C 退出。

有办法吗?

我已经试过了:

command 1 || command 2

但 Ctrl-C 仍然退出。

您可以在后台尝试 运行 命令 1 并捕获 Ctrl + C 发送的信号。

#! /bin/bash
(command 1) &                 # Runs c1 in the background
pid=$!                        # Stores the PID of the subshell
trap "kill -INT $pid" SIGINT  # Makes Ctrl+C kill the background process
wait                          # Waits for completion of c1
trap - SIGINT                 # Restores the default behaviour of Ctrl+C
command 2                     # Runs the second command

要让命令退出但脚本继续按 Ctrl-C,只需设置一个无操作信号陷阱:

trap "true" INT
sleep 30
echo "Continuing"

如果想恢复杀死脚本的行为,可以使用trap - INT

以下应确保如果您按 ctrl-C、command1 以及它可能具有的任何子进程,将获得 SIGINT。

#!/bin/bash

# Use "set -m" to test if "-m" option is currently set
# If set, this will ensure that any subprocesses are started
# as process group leaders (we'll need this later)

if [ -z "${-//[^m]/}" ]  # -m option not already set
then
    set -m
    setm=1
else
    setm=0
fi

# launch the command and capture its pid
command1 &
pid=$!

# install a trap so that if SIGINT is received, then every
# process in the process group of which command1 is leader
# is sent a SIGINT (note the "-" before $pid)
trap "kill -INT -$pid" SIGINT

# wait for command1 to finish (ignoring any other previously launched
# children that finish meanwhile)
wait $pid

# undo "set -m" setting as appropriate
if [ $setm -eq 1 ]
then
    set +m
fi

# cancel the trap
trap - SIGINT

# and carry on
command2

例如,如果 command1 本身是一个 shell 脚本,那么 shell 脚本正在 运行 的命令应该正确终止。

使用 -m 选项的一个轻微副作用是,如果您按下 ctrl-C,您将收到如下消息:

[1]+  Interrupt               command1

这可能会推迟到下一个命令完成之后。您可以在 command2(例如 sleep 0.1)之前插入一个短暂的睡眠,以便在睡眠结束时(在 command2 运行s 之前)而不是在 command2 之后传递任何此类通知。