【问题标题】:terminate whole bash script instead of child process终止整个 bash 脚本而不是子进程
【发布时间】:2015-06-28 20:51:30
【问题描述】:

我有一个运行多个 rsync 命令的脚本。当我执行 ctrl+c 时,只有正在运行的 rsync 命令停止,然后脚本中的下一个命令开始。

如何更改脚本,以便 ctrl+c 停止整个过程而不是仅停止一个命令?

目前脚本中没有逻辑,只是一个接一个地rsync不同的文件夹。

为了举例,我们假设它是

#!/bin/bash
rsync -artv foo/ bar/
rsync -artv another/ folder/

【问题讨论】:

  • This page 表明如果 rsync 表现良好,脚本应该在 SIGINT/Ctrl-C 上终止。我想假设 rsync 表现良好(尽管可能不是)。

标签: linux bash signals


【解决方案1】:

不幸的是,它有点难看。为了确保 bash 在您按下 ctrl-c 时获得 SIGINT,您不能让 rsync 在前台运行。相反,您需要执行以下操作:

#!/bin/bash

trap 'kill $!; exit 1;' INT
rsync -artv foo/ bar/ &
wait
rsync -artv another/ folder/ &
wait

但这并不完全符合您的要求,因为这会将 SIGTERM 而不是 SIGINT 发送到 rsync。不幸的是,因为 rsync 是异步运行的(即在后台),bash 会在忽略 SIGINT 的情况下启动它,因此您不能依赖转发 SIGINT。 (很可能 rsync 会重置其信号处理以接受 SIGINT,但通常使用这种技术,您应该假设正在运行的作业忽略 SIGINT。)

主要问题是,如果 rsync 在前台运行,那么 bash 不会看到 SIGINT,除非您碰巧在一个 rsync 完成之后和下一个 rsync 开始之前发送它。通过在后台运行作业,bash 将看到信号。

请注意,这根本不可靠;这是在 *nix 中处理信号的乐趣之一。

【讨论】:

    【解决方案2】:

    最简单的方法是添加:

    trap 'exit' INT
    

    在脚本的最开始。

    这将在捕获 ctrl+c 组合时执行exit,并完全停止脚本的执行。

    【讨论】:

      猜你喜欢
      • 2011-12-10
      • 1970-01-01
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多