有没有办法检查哪一行数字脚本的bash
“现在”正在执行?
使用bash -x script.sh
看起来很有希望;但是,我需要获取当前的行号。
答案1
$ 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
或者在父 shell 中:
$ cat test.sh
sleep 1m
sleep 1d
$ export PS4='+${LINENO}: '
$ timeout 5 bash -x ./test.sh
+1: sleep 1m
答案2
是的,有办法。
有一个已调用函数的行号数组。
定义这个函数:
f(){ echo "${BASH_LINENO[-2]}"; }
并在您需要行号的任何线路上调用f
,例如:
#!/bin/bash
f(){ echo "${BASH_LINENO[-2]}"; }
f
echo next1
f
echo next2
f
echo next 3
f
将打印:
6
next 1
9
next 2
12
next 3
15
它可以扩展以显示调用的函数的踪迹:
#!/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
将打印:
$ ./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
请注意,上面的echo "$LINENO"
输出始终相同(在本例中为 7)。
答案3
这是一个借用部分的解决方案l0b0 的和多普戈蒂的答案(并且在较小程度上,索隆塔的)。就像这些答案一样,我用它$LINENO
来发现行号;与他们不同的是,我用来trap
触发报告。 bash 的trap
命令描述于重击(1):
trap [-lp] [[arg] sigspec ...]
命令精氨酸当 shell 收到信号时读取并执行信号规范。 … ︙
… 如果信号规范是调试, 命令精氨酸在每个之前执行简单的命令、for
命令、case
命令、select
命令、每个算术for
命令以及在 shell 函数中执行第一个命令之前...
所以这个脚本:
$ 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))
$
printf "%3d: " "$LINENO"
在脚本中的每个命令之前运行该命令,并生成以下输出:
$ ./myscript 3:2017 年 4 月 5 日星期三上午 10:16:17 4:5:2017 年 4 月 5 日星期三 10:16:47 7:8:2017 年 4 月 5 日星期三 10:16:58 10:共4个 -rwxr-xr-x 1我的用户名 我的组4 月 5 日 221 日 10:01 -rwxr-xr-x 1我的用户名 我的组252 四月 5 日 10:01 myscript2 -rw-r--r-- 1我的用户名 我的组132 四月 5 09:59 myscript2.log -rw-r--r-- 1我的用户名 我的组 4 月 5 日 45 日 08:34 other_file 11:13:我的脚本 14:-rwxr-xr-x 1我的用户名 我的组4 月 5 日 221 日 10:01 11:13:myscript2 14:-rwxr-xr-x 1我的用户名 我的组252 四月 5 日 10:01 myscript2 11:13:myscript2.log 14:-rw-r--r-- 1我的用户名 我的组132 四月 5 09:59 myscript2.log 11:13:其他文件 14:-rw-r--r-- 1我的用户名 我的组 4 月 5 日 45 日 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 $
笔记:
- 喜欢l0b0 的回答,这是微创的——只需添加第 2 行。
- 不像l0b0 的回答,这不会显示命令本身 - 但你并没有要求它这样做。
- 第二个
sleep
跨越脚本第 6 行和第 7 行,报告为第 7 行。 - 第 11 行 (
for f in *
) 在该循环的每次迭代之前报告一次for
。 echo "$f"
并ls -ld "$f"
在各自的行(13 和 14)上正确报告。- 第 17 行 (
for ((i=0; i<3; i++))
) 被报告两次 在该循环的每次迭代之前for
,以及在最后一次迭代之后两次。 set -x
与,LINENO
和PS4
(由 POSIX 标准指定)不同,DEBUGtrap
是 bash 扩展,并且不能在所有 shell 中工作。- DEBUG
trap
可以运行任何命令,并且不限于写入脚本的标准输出或标准错误。
问题是,“检查“现在”正在执行的 bash 脚本的行号”,而不指定用户界面。另一种方法是将当前行号不断写入日志文件:
$ diff myscript myscript2 2c2 < trap 'printf "%3d:" "$LINENO"' 调试 --- > exec 6> myscript2.log && trap 'printf "%3d\n" "$LINENO" >&6' 调试 $ ./myscript2 2017 年 4 月 5 日星期三 10:23:50 上午 2017 年 4 月 5 日星期三 10:24:20 上午 2017 年 4 月 5 日星期三 10:24:31 总计 4 -rwxr-xr-x 1我的用户名 我的组4 月 5 日 221 日 10:01 -rwxr-xr-x 1我的用户名 我的组252 四月 5 日 10:01 myscript2 -rw-r--r-- 1我的用户名 我的组 4 月 5 日 24 日 10:23 myscript2.log -rw-r--r-- 1我的用户名 我的组 4 月 5 日 45 日 08:34 other_file 脚本 -rwxr-xr-x 1我的用户名 我的组4 月 5 日 221 日 10:01 脚本2 -rwxr-xr-x 1我的用户名 我的组252 四月 5 日 10:01 myscript2 myscript2.log -rw-r--r-- 1我的用户名 我的组 4 月 5 日 60 日 10:23 myscript2.log 其他文件 -rw-r--r-- 1我的用户名 我的组 4 月 5 日 45 日 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
答案4
#!/bin/bash -x
在脚本开头添加“-x”。然后,每次执行脚本时,它都会回显脚本正在执行的行。就像脚本的执行树一样。