我有一个bash
脚本,它需要将近5秒的时间才能运行。我想调试它,并确定哪些命令花费的时间最长。这样做的最好方法是什么?有没有可以设置的标志?设置#!/bin/bash -vx
并没有真正的帮助。我想要的基本上是按行号执行的时间。如何调试bash脚本并获取每个命令的执行时间
回答
您可以使用set -x
让脚本在执行前打印每个命令。我不知道如何获得自动添加的命令时序。您可以在整个脚本中使用date
命令来标记时间。
可以使用time
工具来衡量你的个人命令/功能的运行时间。
例如:
[[email protected] ~]$ cat times.sh
#!/bin/bash
test_func()
{
sleep 1
echo "test"
}
echo "Running test_func()"
time test_func
echo "Running a 5 second external command"
time sleep 5
运行在类似下面这个脚本的结果:
[[email protected] ~]$ ./times.sh
Running test_func()
test
real 0m1.003s
user 0m0.001s
sys 0m0.001s
Running a 5 second external command
real 0m5.002s
user 0m0.001s
sys 0m0.001s
这是尽可能接近内置bash调试工具的答案,因为它可以从脚本执行开始时间提供整体计时信息。
在脚本的顶部添加此为第二计:
export PS4='+[${SECONDS}s][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x;
相同,但用毫秒来代替:
N=`date +%s%N`; export PS4='+[$(((`date +%s%N`-$N)/1000000))ms][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x;
的最后一个例子可以到微秒级精度,只要记住你正在使用bash :)。
Exampe脚本:
#!/bin/bash
N=`date +%s%N`
export PS4='+[$(((`date +%s%N`-$N)/1000000))ms][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x;
sleep 1
exit
实施例的调试输出:
+[3ms][/root/db_test.sh:5]: sleep 1
+[1012ms][/usr/local/bin/graphite_as_rand_stat.sh:6]: exit
请注意,可以有选择地通过“设置-x”包围它调试脚本的特定部分在在调试结束时调试开始和'调试+ x'。计时数据仍将显示从执行开始正确计数。
附录
为了完整起见,如果你需要的差分时钟数据可以重定向调试信息到一个文件,随后对其进行处理。
鉴于这种示例脚本:
#!/bin/bash
N=`date +%s%N`
export PS4='+[$(((`date +%s%N`-$N)/1000000))ms][${BASH_SOURCE}:${LINENO}]: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x;
sleep 1
for ((i=0;i<2;i++)); do
o=$(($RANDOM*$RANDOM/$RANDOM))
echo $o
sleep 0.$o
done
exit
运行它,而重定向调试到一个文件:
./example.sh 2>example.dbg
和输出与此差动调试定时(覆盖多线):
p=0; cat example.dbg | while read l; do [[ ! ${l%%[*} =~ ^\+ ]] && echo $l && continue; i=`echo $l | sed 's#[^0-9]*\([0-9]\+\).*#\1#'`; echo $l | sed "s#${i}ms#${i}ms+$(($i-$p))ms#"; p=$i; done
输出:
+[2ms+2ms][./example.sh:5]: sleep 1
+[1006ms+1004ms][./example.sh:6]: ((i=0))
+[1009ms+3ms][./example.sh:6]: ((i<2))
+[1011ms+2ms][./example.sh:7]: o=19258
+[1014ms+3ms][./example.sh:8]: echo 19258
+[1016ms+2ms][./example.sh:9]: sleep 0.19258
+[1213ms+197ms][./example.sh:6]: ((i++))
+[1217ms+4ms][./example.sh:6]: ((i<2))
+[1220ms+3ms][./example.sh:7]: o=176
+[1226ms+6ms][./example.sh:8]: echo 176
+[1229ms+3ms][./example.sh:9]: sleep 0.176
+[1442ms+213ms][./example.sh:6]: ((i++))
+[1460ms+18ms][./example.sh:6]: ((i<2))
+[1502ms+42ms][./example.sh:11]: exit
非常好地完成。这个问题被标记为'linux',但由于这些技术在支持bash的所有平台上都可能有用,所以让我补充一点:可悲的是,'%N'在BSD/OSX上不能与'date'一起工作,所以毫秒变体doesn在那里工作。 – mklement0
毫秒变体也是这样做的,但是为了也从'set -x'运行的位置开始测量'$ SECONDS'变体,首先执行'SECONDS = 0'。最后,值得一提的是,测量自身的行为会稍微增加执行时间,而'$ SECONDS'方法则更少。 – mklement0
非常好的答案。另见http://stackoverflow.com/questions/5014823/how-to-profile-a-bash-shell-script –
- 1. bash脚本不执行mongod的命令
- 2. 如何在bash脚本中获取shell命令的中间值
- 3. 如何从节点脚本执行时查看bash命令
- 4. bash脚本执行su命令
- 5. Bash脚本命令不执行
- 6. Bash脚本没有执行命令
- 7. 在bash脚本中执行sed命令
- 8. Bash脚本:无法执行mencoder命令!
- 9. 在bash脚本中执行Postgresql命令
- 10. 从Cygwin bash脚本执行Windows命令
- 11. 如何在脚本执行时间内每小时运行一次cron命令?
- 12. Bash脚本:在单行执行多个命令&&获取返回码
- 13. bash脚本ssh并运行命令
- 14. 编写获取命令并执行它的脚本
- 15. 获取大量bash脚本的执行时间信息
- 16. bash脚本改变目录并执行带参数的命令
- 17. bash脚本找到并执行更复杂的命令
- 18. 在bash脚本中运行两个正在执行的命令
- 19. 如何Ant脚本为每个文件执行命令
- 20. 如何从bash脚本执行tshark的命令
- 21. 如何在远程系统上执行BASH脚本的命令?
- 22. Bash脚本并在命令行上手动运行命令
- 23. 如何在python脚本中执行多个命令的命令
- 24. 在bash中的每个命令之后执行命令
- 25. 如何查看执行脚本时执行的命令?
- 26. 如何查看每个用户的linux命令执行时间
- 27. bash脚本:执行命令并将其输出传递给awk
- 28. 如何并行Python中执行多个命令的bash
- 29. 如何在后台使用bash脚本执行grep链命令
- 30. bash脚本如何从变量执行命令
你为什么这么不耐烦?在运行脚本时花费一个小时来削减奇数秒? –
该脚本运行频率很高,需要对其进行优化。 – Justin
经常多久?它的速度是很重要的,也许用C++编写(例如)是一个更好的选择。除此之外为什么不发布脚本? –