docker-compose、less 和 SIGINT

docker-compose、less 和 SIGINT

我有一个使用 启动测试环境的脚本docker-compose。该脚本通过 less 将许多 docker 容器的混合 stdout 通过管道传输到 stdout:

# This is part of a larger script with some setup and teardown.
$ docker-compose up --build | less +F -r

less此处显示了不良行为:当点击Ctrl+时Cdocker-compose收到它并自行关闭。所需的行为只是中断以下 ( +F) 功能less(就像查看大型日志时所做的那样)。

我想在最佳情况下实现什么:用第一个Ctrl+中断以下内容,并在第二个+C上退出整个测试环境。CtrlC

我玩了一下并尝试了以下操作:

  • 注册一个trap 'do_exit' SIGINT将实现上述逻辑的。但仍然在+docker-compose上退出。CtrlC
  • 用于trap '' SIGINT完全捕获 SIGNT。docker-compose但仍然凭空得到了Ctrl+ 。C

另一个观察:

这适用于zsh:((trap '' SIGINT && docker-compose up --build | less +F -r)它根本不对 SIGINT 做出反应)同一行在 bash 中的行为不同,并被 SIGINT 杀死。

这是完整的(有问题的)脚本供参考:

#!/usr/bin/env bash

service_name=xxx

for dir in ../1 ../2 ../3; do
    if [ ! -d "$dir" ]; then
      echo "docker compose requires $dir, please check $dir do exist in the same folder level"
      exit 0
    fi
done

docker-compose up --build | less +F -r

if [ ! $? -eq 0 ]; then
    echo "Couldn't start service or Control-C was pressed"
    echo "cleaning up"
    docker-compose down
    exit $?
fi

docker-compose rm --all --force

有这方面的解决办法或者经验吗?

--

编辑:我也尝试过这里的解决方案,但没有成功:

答案1

读完这篇文章后我明白了:

解决方案是set -m在脚本开始处执行。这会导致 bash 为每个进程创建一个新的进程组,而不是导致将 SIGINT 发送到脚本中的每个进程。

作为参考,固定脚本如下所示:

#!/usr/bin/env bash

set -m
set -e

service_name=xxx

for dir in ../1 ../2 ../3; do
    if [ ! -d "$dir" ]; then
      echo "docker compose requires $dir, please check $dir do exist in the same folder level"
      exit 0
    fi
done

TEMP_LOG_FILE=$(mktemp --suffix '-dev-env-log')
(trap '' SIGINT && docker-compose up --build > ${TEMP_LOG_FILE}) &
less +F -r ${TEMP_LOG_FILE}
rm ${TEMP_LOG_FILE}

echo "Less was quit, stopping containers..."


if [ ! $? -eq 0 ]; then
    echo "could not start service or Control-C was pressed"
    echo "cleaning up"
    docker-compose down
    exit $?
fi

docker-compose down
docker-compose rm --all --force

相关内容