簡體   English   中英

如何調試bash腳本並獲得每個命令的執行時間

[英]How to debug a bash script and get execution time per command

我有一個bash腳本,需要將近5秒鍾才能運行。 我想調試它,並確定哪些命令花費的時間最長。 這樣做的最佳方式是什么? 我可以設置一個標志嗎? 設置#!/bin/bash -vx並沒有什么幫助。 我想要的基本上是按行號執行時間。

這是盡可能接近內置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 :)。

示例腳本:

#!/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

請記住,您可以選擇性地調試腳本的特定部分,方法是將其封裝在調試開始時的“set -x”和調試結束時的“debug + 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

您可以使用time實用程序來測量各個命令/功能的運行時間。

例如:

[ben@imac ~]$ 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

運行該腳本會產生以下內容:

[ben@imac ~]$ ./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

您可以使用set -x讓腳本在執行之前打印每個命令。 我不知道如何自動添加命令時序。 您可以在整個腳本中使用date命令來標記時間。

嘗試這個:

sed 's/^\([^#]\)/time \1/' script.sh>tmp.sh && ./tmp.sh

它為所有非命令行添加時間命令

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM