use*_*371 16 bash monitoring shell-script
有没有一种方法来检查其行数一的bash脚本执行“现在”?
使用bash -x script.sh看起来很有希望;但是,我需要获取当前行号。
l0b*_*0b0 21
$ cat test.sh
#!/usr/bin/env bash
set -x
PS4='+${LINENO}: '
sleep 1m
sleep 1d
$ timeout 5 ./test.sh
+3: PS4='+${LINENO}: '
+5: sleep 1m
Run Code Online (Sandbox Code Playgroud)
$ cat test.sh
sleep 1m
sleep 1d
$ export PS4='+${LINENO}: '
$ timeout 5 bash -x ./test.sh
+1: sleep 1m
Run Code Online (Sandbox Code Playgroud)
ImH*_*ere 10
是的,有办法。
有一个行号数组,其中调用了一个函数。
定义这个函数:
f(){ echo "${BASH_LINENO[-2]}"; }
Run Code Online (Sandbox Code Playgroud)
并f在您想要行号的任何行上调用,例如:
#!/bin/bash
f(){ echo "${BASH_LINENO[-2]}"; }
f
echo next1
f
echo next2
f
echo next 3
f
Run Code Online (Sandbox Code Playgroud)
将打印:
6
next 1
9
next 2
12
next 3
15
Run Code Online (Sandbox Code Playgroud)
它可以扩展以显示调用的函数的踪迹:
#!/bin/bash
f(){
for ((i=${#BASH_LINENO[@]}-1;i>=0;i--)); do
printf '<%s:%s> ' "${FUNCNAME[i]}" "${BASH_LINENO[i]}";
done
echo "$LINENO"
}
SomeOtherFunction(){ echo -n "test the line numbering: "; f; }
f
echo next 1
echo -n " This line numbering: "; f
SomeOtherFunction
echo next 2
echo -n " This line numbering: "; f
SomeOtherFunction
echo next 3
echo -n " This line numbering: "; f
Run Code Online (Sandbox Code Playgroud)
这将打印:
$ ./script
<main:0> <f:12> 7
next 1
This line numbering: <main:0> <f:15> 7
test the line numbering: <main:0> <SomeOtherFunction:16> <f:10> 7
next 2
This line numbering: <main:0> <f:19> 7
test the line numbering: <main:0> <SomeOtherFunction:20> <f:10> 7
next 3
This line numbering: <main:0> <f:23> 7
Run Code Online (Sandbox Code Playgroud)
请注意,上面的echo "$LINENO"输出始终相同(在这种情况下为 7)。
这是一个借用了l0b0和DopeGhoti 的部分答案(以及在较小程度上,sorontar 的答案)的解决方案。像那些答案一样,我的用于$LINENO发现行号;与他们不同,我trap用来触发报告。bash 的trap命令在bash(1) 中描述:
trap [-lp] [[arg] sigspec ...]当 shell 接收到信号sigspec .??...时,将读取并执行 命令arg。????? ……?如果sigspec是DEBUG,则命令arg在每个简单命令、 命令、命令、命令、每个算术命令之前执行,以及在 shell 函数中执行第一个命令之前……
forcaseselectfor
所以这个脚本:
$ cat -n myscript
1 #!/bin/bash
2 trap 'printf "%3d: " "$LINENO"' DEBUG
3 date
4 sleep 30
5 date
6 sleep \
7 11
8 date
9
10 ls -l
11 for f in *
12 do
13 echo "$f" &&
14 ls -ld "$f"
15 done
16
17 for ((i=0; i<3; i++))
18 do
19 echo "i = $i"; date
20 done
21
22 echo $((5+25+12))
$
Run Code Online (Sandbox Code Playgroud)
printf "%3d: " "$LINENO"在脚本中的每个命令之前运行该命令,并产生以下输出:
$ ./我的脚本 3:2017 年 4 月 5 日,星期三 10:16:17 4:5: 2017 年 4 月 5 日,星期三 10:16:47 7:8: 2017 年 4 月 5 日,星期三 10:16:58 AM 10:共 4 个 -rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript -rwxr-xr-x 1 myusername mygroup 252 Apr 5 10:01 myscript2 -rw-r--r-- 1 myusername mygroup 132 Apr 5 09:59 myscript2.log -rw-r--r-- 1 myusername mygroup 45 Apr 5 08:34 other_file 11:13:我的脚本 14:-rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript 11:13:我的脚本2 14:-rwxr-xr-x 1 myusername mygroup 252 Apr 5 10:01 myscript2 11:13:myscript2.log 14:-rw-r--r-- 1 myusername mygroup 132 Apr 5 09:59 myscript2.log 11:13:其他文件 14:-rw-r--r-- 1 myusername mygroup 45 Apr 5 08:34 other_file 17:17:19:我=0 19:2017 年 4 月 5 日,星期三 10:16:59 17:17:19:我= 1 19:2017 年 4 月 5 日,星期三 10:16:59 17:17:19:我= 2 19:2017 年 4 月 5 日,星期三 10:16:59 17:17:22:42 $
笔记:
sleep跨越脚本第 6 行和第 7 行,报告为第 7 行。for f in *) 在该for循环的每次迭代之前报告一次。echo "$f"并ls -ld "$f"在各自的行(13 和 14)上正确报告。for ((i=0; i<3; i++)))
在该循环的每次迭代之前报告两次for,并在最后一次迭代之后报告两次。set -x,LINENO和PS4
(由 POSIX 标准指定)不同,DEBUGtrap是一个 bash 扩展,不能在所有 shell 中工作。trap可以运行任何命令,并且不限于写入脚本的标准输出或标准错误。问题是,?«检查 bash 脚本的哪个行号“现在”正在执行»?没有指定用户界面。另一种方法是不断地将当前行号写入日志文件:
$ diff myscript myscript2 2c2 < 陷阱 'printf "%3d: " "$LINENO"' 调试 --- > exec 6> myscript2.log && trap 'printf "%3d\n" "$LINENO" >&6' DEBUG $ ./myscript2 2017 年 4 月 5 日,星期三 10:23:50 2017 年 4 月 5 日,星期三 10:24:20 2017 年 4 月 5 日,星期三 10:24:31 共 4 个 -rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript -rwxr-xr-x 1 myusername mygroup 252 Apr 5 10:01 myscript2 -rw-r--r-- 1 myusername mygroup 24 Apr 5 10:23 myscript2.log -rw-r--r-- 1 myusername mygroup 45 Apr 5 08:34 other_file 我的脚本 -rwxr-xr-x 1 myusername mygroup 221 Apr 5 10:01 myscript 我的脚本2 -rwxr-xr-x 1 myusername mygroup 252 Apr 5 10:01 myscript2 myscript2.log -rw-r--r-- 1 myusername mygroup 60 Apr 5 10:23 myscript2.log 其他文件 -rw-r--r-- 1 myusername mygroup 45 Apr 5 08:34 other_file 我 = 0 2017 年 4 月 5 日,星期三 10:24:31 我 = 1 2017 年 4 月 5 日,星期三 10:24:31 我 = 2 2017 年 4 月 5 日,星期三 10:24:31 42 $
我们可以通过myscript2.log从另一个终端监视文件的内容来监视此脚本的执行。例如,在第二个sleep,
$ tail myscript2.log
3
4
5
7
Run Code Online (Sandbox Code Playgroud)
您可以echo $LINENO在脚本中,它应该输出该命令恰好位于的任何行。
#!/bin/bash
echo $LINENO
$ ./foo.sh
2
Run Code Online (Sandbox Code Playgroud)