问题标签 [bash-trap]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
367 浏览

bash - bash脚本退出时如何杀死所有子进程?

我正在使用命名管道在 3 种进程之间进行通信:生产者、一些读者和一些作者。然后我创建了一个脚本,它简单地运行所有进程,我希望当 run.sh 进程被杀死或它终止时,所有子进程也被杀死。run.sh 脚本如下:

该脚本非常简单,但似乎不起作用,因为我仍然可以看到一些进程正在运行(只是 producer.sh 已被杀死)。

所以我必须用这个杀死:

我怎样才能让它工作?

更新1: 似乎已经在后台运行的作业&可以抵抗信号SIGINT,所以简单kill是没用的。使用kill -9kill -TERM在陷阱中他们会收到信号,但他们仍然活着,只有producer.sh被正确杀死。

更新 2: reader_one.sh并且writer_one.sh正在等待命名管道中的数据。

更新3: 这里的代码read_one.sh; 可能原因是子外壳,因为管道就在while

0 投票
2 回答
1761 浏览

bash - 从bash中的stdin读取时如何处理中断信号

我正在玩 bash 读取功能。我喜欢我目前外壳上的一个简单层。read -e 执行制表符完成和先前的命令,并使用 ctrl+d 发送 EOF 让我回到原来的 shell。这是我的参考:

Bash(或其他 shell):用函数/脚本包装所有命令

我想要一些处理 SIGINT 的帮助,ctrl+c。在普通的 shell 中,如果您开始输入并在中途按 ^C,它会立即结束该行。对于这个简单的示例,在 ^C 之后,我仍然必须在注册之前按回车键。

如何保留 readline 所做的好事,但仍能正确处理 SIGINT?理想情况下,它会将 continue 语句发送到 while read 循环,或者以某种方式将 \n 发送到我的读取正在等待的 STDIN。

示例代码:

0 投票
2 回答
254 浏览

python - 在 shell 脚本中使陷阱静音

我有一个 shell 脚本,我用它来调用许多 python 脚本。我在我的 shell 脚本中添加了一个陷阱来捕获 ctrl+c 并退出。但是,如果一个 python 脚本正在运行并且我按下 ctrl+c,它也会显示正在执行的 python 脚本块!我不要那个。我知道更好的方法是在我的 python 脚本中添加 KeyboardInterrupt,但这需要付出很多努力。我想要一个解决方案,当我按下 ctrl+c 时,te 控制脚本执行以静默方式结束。

例如:a.sh:

b.py:

当我运行 a.sh 并按 ctrl+c 时,我不想看到这样的 python 块:

我希望它以简单的“键盘中断”消息退出。

0 投票
1 回答
1018 浏览

bash - Bash 陷阱,捕获并将它们作为参数传递给同一函数

我正在开发一个管理一些陷阱的脚本。一开始我只用这段代码管理 INT 和 SIGTSTP 并且效果很好:

然后我尝试添加我想要管理的新陷阱,即 SIGINT 和 SIGHUP。在第一个实例中,我这样做了(这是有效的):

然后,我决定根据陷阱在退出时做不同的事情,我不想为每个人创建不同的功能。我知道在 bash 中,您可以使用命名法遍历函数上的参数for item in $@; do,所以我尝试了,但尝试区分陷阱类型似乎不起作用。我制作了这个不起作用的代码。

有什么帮助吗?必须有一种方法来改进我的代码,只对所有陷阱使用一个函数,但我不知道如何......

0 投票
2 回答
489 浏览

linux - Bash Trap:如何获取非零状态的子进程的行号

对于 Bash 程序:

输出:

我正在寻找一种方法来获得它,以便以非零状态退出的子shell被捕获trap并显示失败子shell的行号。在上面的示例中,我正在寻找第 20 行作为结果。我注意到如果错误不在子 shell 中,我会得到想要的行号(见false上文)。

我尝试将陷阱移动到子shell 之前以检查行号9是否实际连接到陷阱调用,但我得到了相同的结果。我还尝试将setandshopt条目也放入子外壳中——同样没有改变行为。

环境:

  • bash-4.2.46-21.el7_3.x86_64:这是一项要求,但不要求符合 POSIX。我也对后来的 Bash 版本(4.2+)感兴趣。
  • CentOS 7+:虽然主要对 CentOS 感兴趣,但我最终将需要它用于部署在 Ubuntu 16.04+ 和 CentOS 6 上的 Bash 脚本。

是否可以获得返回非零状态的子进程的行号?如果不可能,是否有任何文件可以证明这一点?如果存在解决方案,它应该可以很好地扩展,而无需在代码中进行不必要的修饰。

0 投票
1 回答
5982 浏览

bash - Bash 中陷阱的退出代码

这是myscript.sh

当我运行它时:

为什么脚本的退出码和不带trap的退出码一样?通常,函数会隐式返回最后执行的命令的退出代码。在这种情况下:

  1. 回声返回 0
  2. 我希望mytrap返回 0
  3. 由于mytrap是执行的最后一个函数,因此脚本应返回 0

为什么不是这样?我的想法哪里错了?

0 投票
1 回答
145 浏览

bash - 是否可以找到一种方法来执行 set -e/ERR subshel​​l 捕获对 && 和 || 免疫的方法?限制?

虽然Bash 手册页指出:

如果失败的命令是 ... 在 && 或 || 中执行的命令的一部分,则不会执行 ERR 陷阱 列表 ...

我希望 subshel​​l 中的代码处于不同的上下文中,并且不受上述限制。下面的代码表明,即使是 subshel​​l 也不能免受此限制:

上面的代码有以下输出:

我目前的解决方法是使用文件持久性来保存错误状态,MyTrap然后在调用者中检查返回码。例如:

上面的输出现在是:

所以,问题是:是否可以找到一种方法来执行 set -e/ERR 子shell 捕获,它不受上述解决方法的影响&&和限制?||

注:此问题适用于:

  • Bash 4.2 及更高版本
  • Red Hat 7、CentOS 7 和相关发行版(即不是 Debian 等)
  • 不得使用第三方软件。软件包必须可用,例如,通过 [CentOS-7-x86_64-DVD-1611.iso][2] 存储库 iso 中的 OS-provider 软件包(对于 RHEL 7、Fedora 7 等类似)。
0 投票
2 回答
133 浏览

linux - 我的第一个 bash 脚本中的错误处理问题

好的,所以我是 bash 脚本的初学者,我知道这个问题的措辞可能有点尴尬,但我会尽可能清楚!

我编写了以下脚本来在文件夹中创建存储库的备份。脚本如下:

当不带参数调用该脚本时,此脚本成功生成 'var/svn' 中所有存储库的 .gzip 备份,并创建称为参数的特定存储库的 .gzip 备份。伟大的!

但是,如果脚本使用与存在的存储库不对应的参数运行,则程序将崩溃并显示错误消息:svnadmin: E000002: Can't open file '/var/svn/ada/format': No such file or directory. 我想要实现的是捕捉这个错误并将更用户友好的输出打印到控制台。我一直在尝试使用“陷阱”来做到这一点。

首先,我添加了以下行:

...然后我在最后一个 for 循环中将错误推送到 /dev/null :

我在我所做的地方推送到 /dev/null 文件,因为这是程序出错的地方。但是,该脚本似乎不再起作用。我在这里做错了什么?与2>/dev/null在一行中间有问题吗?如果是这样,我该如何重构这段代码,使其不需要管道中间的管道?

非常感谢您的帮助,我希望我的问题相当清楚!为了确认,最终的非工作代码如下:

0 投票
1 回答
463 浏览

shell - 在 Shell 脚本期间杀死 NPM 产生的所有进程

我有一个大致如下所示的 shell 脚本:

为了确保长时间运行的脚本持续运行,但为了防止多个实例并行运行,我通过 cron 调用它,使用:

我尝试使用陷阱并将其添加到脚本的开头,但没有运气:

上述的不同变体也不起作用,例如trap "kill -HUP -$$". 似乎陷阱甚至没有被执行(大概是因为它正在等待所有实例$NPM run -s long_running_script完成?)。

我可以从不同的脚本中杀死进程,知道孩子和孙子的名字,然后执行pkill,但我更喜欢更通用的解决方案。有没有办法在不手动跟踪所有生成的进程及其后续子进程的情况下杀死从 shell 脚本生成的所有进程?

更新

向脚本片段添加了更多详细信息,以显示我正在管道输出。这是 NPM 产生的进程的快照(在每个循环的迭代中):

以及来自 lsof 的相应输出:

更新 2

以下是我调用 时会发生的情况fuser -k,它只会杀死顶级进程和 npm,但不会杀死它的孙子进程:

0 投票
0 回答
74 浏览

bash - Bash errexit 堆栈回溯故障

我从 bash 脚本中的堆栈回溯中受益匪浅。但是,直到今天我花时间制作了一个最小的工作示例,我总是忽略了周期性故障:

我有点希望当 bad() 返回错误代码时会在第 7 行触发错误陷阱,但是好的,bash 有很多小方法。真正的问题是,我在这里看不到足够的信息来给出正确的堆栈回溯。函数 good() 中的第 7 行肯定是此错误的堆栈回溯的一部分,无论您如何剪切它。

我可以想象一些非常讨厌的解决方法,但希望我遗漏了一些东西,有人可以指出如何在这种情况下正确地将第 7 行识别为堆栈回溯的一部分。

我担心这是不幸的 bash 行为,它在触发陷阱之前已经从堆栈中弹出 bad() 并且在将当前行#弹出给调用者(第 7 行)之前,实际上最终报告第 6 行属于好()而不是坏()。