我试图将一个文件复制到其他目录,并在调用中断时收到错误消息.
剧本 :
#!/bin/bash
PATH=~/MkFile/
exitfn () {
trap SIGINT # Resore signal handling for SIGINT
echo ; echo 'Called ctrl + c ' # Growl at user,
cp ./BKP/temp.txt $PATH/backup.txt
exit # then exit script.
}
trap "exitfn" INT # Set up SIGINT trap to call function.ii
read -p "What? "
echo "You said: $REPLY"
# reset all traps##
trap - 0 SIGINT
Run Code Online (Sandbox Code Playgroud)
输出:
./signal.sh
What? ^C
Called ctrl + c
./signal.sh: line 9: cp: command not found
Run Code Online (Sandbox Code Playgroud)
你知道这个剧本有什么问题吗?
鉴于此hack.c程序:
#include <stdio.h>
main()
{
int i=0;
for(i=0; i<100; i++) {
printf("%d\n", i);
sleep(5);
}
}
Run Code Online (Sandbox Code Playgroud)
和这个hack.sh bash脚本:
#!/bin/bash
./hack
Run Code Online (Sandbox Code Playgroud)
如果我运行hack.sh,则会创建两个进程 - 一个用于bash,一个用于C任务.如果TERM信号被发送到bash进程,则C进程不受伤害.
现在,假设原始bash是使用Runtime.exec()从Java程序启动的,所以我对它的唯一控制是Process.destroy()(它将TERM发送到bash进程)?假设我希望 C进程与启动它的bash一起死掉?
我一直在用bash尝试这样的事情:
#!/bin/bash
trap "kill -TERM -$$; exit" TERM
./hack
Run Code Online (Sandbox Code Playgroud)
即一个陷阱子句,它捕获TERM信号并将其重新广播到整个进程组.这对我不起作用 - 其中包含该陷阱子句的bash进程忽略了 TERM信号.
我在这里错过了什么?
运行以下代码段:
#!/bin/bash
function preexec ()
{
echo -e "\n-->preexec command: $BASH_COMMAND"
}
trap 'preexec' DEBUG
function testfunc ()
{
echo "testfunc called $1"
}
testfunc "main"
source "source.sh"
exit 0
Run Code Online (Sandbox Code Playgroud)
其中source.sh是
#!/bin/bash
testfunc "source"
Run Code Online (Sandbox Code Playgroud)
得到:
-->preexec command: testfunc "main"
testfunc called main
-->preexec command: source "source.sh"
testfunc called source
-->preexec command: exit 0
Run Code Online (Sandbox Code Playgroud)
这意味着源文件中的每个命令都不会被DEBUG陷阱捕获.
事实上,如果我添加该行
trap 'preexec' DEBUG
Run Code Online (Sandbox Code Playgroud)
在source.sh内部作为第二行,一切都按照需要工作(源文件中的命令也被捕获).
如何将此作为默认行为,以避免为我需要提供的任何文件重复上述行?换句话说:有没有机会告诉源文件继承DEBUG陷阱?
我想在我的Bash脚本中进行清理操作,如下所示:
#! /bin/bash
set -eu
trap 'echo "E: failed with exitcode $?" 1>&2' ERR
true
false
Run Code Online (Sandbox Code Playgroud)
使用$?脑海作为一种自然选择,但事实并非如此.它总是包含0.有什么方法可以"窥探" ERR陷阱中的exitcode 吗?
[更新:]我不知道我之前测试过的是什么.这段代码就像一个魅力,所以我把它留在这里作为一个小而好的例子.
我试图将 stdout 和 stderr 中的所有内容记录到日志文件中,并仍然保留控制台。为此,我只是将:附加|& tee -a log_file.log到每个命令中。
但是,如果脚本期间发生任何错误,我还想运行自定义命令。为此,我在脚本的开头添加了以下内容:trap "echo Non-zero exit code detected" ERR。
问题是通过使用管道运算符,陷阱中的回显不再执行。
脚本 1,不带管道:
$cat test.sh
#!/bin/bash
trap "echo Non-zero exit code detected!" ERR
function fail_please()
{
echo "Returning non-zero exit code!"
return 1
}
fail_please
Run Code Online (Sandbox Code Playgroud)
输出1:
$ ./test.sh
Returning non-zero exit code!
Non-zero exit code detected!
Run Code Online (Sandbox Code Playgroud)
脚本 2,带管道:
$ cat test.sh
#!/bin/bash
trap "echo Non-zero exit code detected!" ERR
function fail_please()
{
echo "Returning non-zero exit code!"
return 1
}
fail_please …Run Code Online (Sandbox Code Playgroud) 下面是我正在编写的脚本的简化方案.程序必须以不同的方式获取参数,因此可以对多个函数进行精细划分.
问题是来自深层函数的返回值的链式加载在陷阱上中断,其中要检查结果以显示消息.
#! /usr/bin/env bash
check_a_param() {
[ "$1" = return_ok ] && return 0 || return 3
}
check_params() {
# This trap should catch negative results from the functions
# performing actual checks, like check_a_param() below.
return_trap() {
local retval=$?
[ $retval -ne 0 ] && echo 'Bad, bad… Dropping to manual setup.'
return $retval
}
# check_params can be called from different functions, not only
# setup(). But the other functions don’t care about the return value …Run Code Online (Sandbox Code Playgroud) 有没有办法检查trapBash中已设置的内容(在当前会话或脚本中)?
理想情况下,我希望能够获得trap分配给它们的信号列表,但如果不可能,我可以单独检查每个信号.
我可以编写可以很好地捕获的 shell 脚本SIGINT,但我似乎无法捕获SIGQUIT.
#!/bin/bash
function die {
echo "Dying on signal $1"
exit 0
}
trap 'die "SIGINT"' SIGINT
trap 'die "SIGQUIT"' SIGQUIT
while true; do
echo "sleeping..."
sleep 5
done
Run Code Online (Sandbox Code Playgroud)
执行此脚本并按下CTRL-C具有所需的效果,但是按下CTRL-\(据我所知,应该触发)除了在终端中SIGQUIT打印之外没有任何作用。^\为什么?
我有两个运行理论。首先,SIGINT和 的语义SIGQUIT不同,SIGQUIT仅发送到子进程sleep,而同时SIGINT发送到子进程和父 bash 进程。如果是这种情况,它在哪里记录?
我的第二个理论是 bash 不仅默认忽略(即有一个无操作处理程序)SIGQUIT(如手册页所示),而且根本不允许它被捕获。该理论与第一个理论重叠,因为父级和子级都可能出现这种情况SIGQUIT,但父级 ( bash) 无法捕获它。如果是这种情况,有什么方法可以捕获SIGQUITbash 脚本吗?...也许shopt我可以设置一些?
编辑:这是在 Ubuntu 10.10 上的 …
如果带有EXIT陷阱的Bash脚本中出现语法错误,是否可以将退出代码传播给调用者?例如,如果我有:
#! /bin/bash
set -eu
trap "echo dying!!" EXIT
echo yeah
echo $UNBOUND_VARIABLE
echo boo
Run Code Online (Sandbox Code Playgroud)
然后,即使脚本没有真正成功结束,运行它也会提供退出代码0:
$ bash test.sh
yeah
test.sh: line 8: UNBOUND_VARIABLE: unbound variable
dying!!
$ echo $?
0
Run Code Online (Sandbox Code Playgroud)
但是如果我注释掉退出陷阱,则脚本返回1.或者,如果我使用返回非零(例如/bin/false)的命令替换带有未绑定变量的行,则该退出值将按照我希望的方式传播.
根据man bash,
set -e如果(剪断)立即退出。如果设置了上的陷阱
ERR,则会在 shell 退出之前执行。
但是,下面的脚本不会调用ERR陷阱。
trap 'echo ERR; sleep 1' ERR
trap 'echo EXIT; sleep 1' EXIT
set -e
array=(a b c)
echo $(( ${#array[@] - 1)) #note the closing bracket } is forgotten
echo "after"
Run Code Online (Sandbox Code Playgroud)
预期结果是
$ bash script.sh
4.sh: line 7: ${#array[@] - 1: bad substitution
ERR
EXIT
# and then shell exits
Run Code Online (Sandbox Code Playgroud)
实际结果是
$ bash script.sh
4.sh: line 7: ${#array[@] - 1: bad substitution
EXIT
# and then …Run Code Online (Sandbox Code Playgroud)