yae*_*ael 35 linux scripting bash logs shell-script
如何在 Bash 中找到发生错误的行号?
我创建了以下带有行号的简单脚本来解释我们需要什么。该脚本将从中复制文件
cp $file1 $file2
cp $file3 $file4
Run Code Online (Sandbox Code Playgroud)
当其中一个cp命令失败时,该函数将以exit 1 退出。我们希望向函数添加还打印带有行号(例如,8 或 12)的错误的功能。
这可能吗?
1 #!/bin/bash
2
3
4 function in_case_fail {
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6 }
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
Run Code Online (Sandbox Code Playgroud)
slm*_*slm 44
与其使用您的函数,不如使用此方法:
$ cat yael.bash
#!/bin/bash
set -eE -o functrace
file1=f1
file2=f2
file3=f3
file4=f4
failure() {
local lineno=$1
local msg=$2
echo "Failed at $lineno: $msg"
}
trap 'failure ${LINENO} "$BASH_COMMAND"' ERR
cp -- "$file1" "$file2"
cp -- "$file3" "$file4"
Run Code Online (Sandbox Code Playgroud)
这是通过捕获 ERR 然后failure()使用当前行号 + 执行的 bash 命令调用函数来工作的。
在这里,我没有注意创建文件f1、f2、f3、 或f4。当我运行上面的脚本时:
$ ./yael.bash
cp: cannot stat ‘f1’: No such file or directory
Failed at 17: cp -- "$file1" "$file2"
Run Code Online (Sandbox Code Playgroud)
它失败,报告已执行的行号加命令。
ilk*_*chu 17
除了LINENO包含当前行号之外,还有BASH_LINENOand FUNCNAME(and BASH_SOURCE) 数组包含调用它们的函数名称和行号。
所以你可以做这样的事情:
#!/bin/bash
error() {
printf "'%s' failed with exit code %d in function '%s' at line %d.\n" "${1-something}" "$?" "${FUNCNAME[1]}" "${BASH_LINENO[0]}"
}
foo() {
( exit 0 ) || error "this thing"
( exit 123 ) || error "that thing"
}
foo
Run Code Online (Sandbox Code Playgroud)
运行会打印
'that thing' failed with exit code 123 in function 'foo' at line 9.
Run Code Online (Sandbox Code Playgroud)
如果您使用set -e, 或trap ... ERR自动检测错误,请注意它们有一些警告。包含脚本当时正在做什么的描述也更难(就像您在示例中所做的那样),尽管这对普通用户来说可能比仅行号更有用。
有关set -e与其他人的问题,请参见例如这些:
meu*_*euh 15
Bash 有一个内置变量$LINENO,它在语句中被当前行号替换,所以你可以这样做
in_case_fail $? "at $LINENO: cp $file1 $file2"
Run Code Online (Sandbox Code Playgroud)
您还可以尝试trap ... ERR在命令失败时使用which running(如果未测试结果)。例如:
trap 'rc=$?; echo "error code $rc at $LINENO"; exit $rc' ERR
Run Code Online (Sandbox Code Playgroud)
然后,如果像这样的命令cp $file1 $file2失败,您将收到带有行号和退出的错误消息。您还会在变量中发现错误的命令$BASH_COMMAND(尽管没有任何重定向等)。