2012-04-26 73 views
1

任何人都知道更好的方法來做到這一點,它是更快?日期爲什麼這麼慢?


#!/bin/bash 

declare -A clientarray 
file=$1 
timer=$2 
e=$(date --date "now +$timer second" +%s) 

while read line 
do 

    if [ -n "${clientarray[$line]}" ]; then 
      let "clientarray[$line]=clientarray[$line]+1" 
      echo "$line: ${clientarray[$line]}" 

    elif [ -z "${clientarray[$line]}" ]; then 
      clientarray[$line]=1 
      echo "$line: ${clientarray[$line]}" 

    fi 
    if [ $(date +%s) -gt $e ]; then 
        e=$(date --date "now +$timer second" +%s) 

    fi 
done < <(tail -F $file | gawk -F"]" '/]/ {print $1}') 

這裏是行的一個示例::

someline] 
someline2] 
somethingidontwant 
someline3] 
somethingelseidontwant 
someline4] 

並調用腳本:

此當前推動每秒高線到該腳本時是慢
bash script.sh somelogfile.log 1 

如果我註釋掉if邏輯最後它變得非常快,但速度下降2/3rds。與光伏測試它:

(這是與如果邏輯):

[email protected]:~/graphs$ tail -F somelogfile.log | pv -N RAW -lc >/dev/null | 
         > bash script.sh somelogfile.log 1 | pv -N SCP -lc >/dev/null 

    RAW: 2.18k 0:00:16 [ 493/s ] [     <=>        ] 
    SCP: 593 0:00:16 [ 150/s ] [    <=>         ] 

(這是不)

[email protected]:~/graphs$ tail -F somelogfile.log | pv -N RAW -lc >/dev/null | 
         > bash script.sh somelogfile.log 1 | pv -N SCP -lc >/dev/null 

    RAW: 7.69k 0:00:15 [512/s] [          <=>   ] 
    SCP: 7.6k 0:00:15 [503/s] [        <=>     ] 

讓我知道如果我的思念在我的腳本或測試的東西側面,特別是任何「DOH!」的。 我認爲在這一點上,我會很喜歡=)

+0

您正在閱讀'$ line',但未在顯示的代碼中使用它。這是否將代碼剝離到最低限度的再現?同樣,除非定期更新,否則您不會使用'$ e'做任何事情。在每次迭代中必須運行外部命令('date')的事實總是會使得進程比只有內部命令執行時慢。最終,你可能會更好地使用Python或Perl或類似的東西;它可以避免新的流程開銷,同時更簡單地進行日期計算。 – 2012-04-26 18:46:59

+0

修復了這個問題,對不起,我通常使用我來代替行,我只是放了行,因爲這是讀取時使用的常見示例,並且錯過了更改腳本的主體。 – patch 2012-04-27 14:01:37

+0

練習編寫代碼是一個不錯的主意,因此您不需要在公開發布代碼之前對其進行修改。那麼你不會遇到這樣的問題。 – 2012-04-27 14:26:12

回答

2

作爲一個猜測,我會說這可能是因爲,去年if ... fi塊增加了每次迭代兩個非內置命令。循環中的所有其他內容都是bash buildins,執行速度更快。有了它,您可以在測試中撥打date,並在if的正文中撥打另一個。此外,date --date每次調用時都必須解析並評估"now +$timer second"表達式,但由於​​的一般性,這可能不是非常快速。如果我是你,我會嘗試用腳本語言重新實現它,並使用更多的本地處理日期/時間:Perl,Ruby,Python,無論你喜歡什麼。

也似乎有一個bug:

if [ `date +%s` > $e ] ... 

這是說:執行命令date +%s和插值輸出(比如12345)到另一個命令[ 12345 > $e ](到目前爲止好)。該命令說:使用兩個參數(12345])運行[內建,並將其標準輸出流重定向到一個名爲值$e(uh-oh)的文件。您可能想在此處使用-gt而不是>

+0

或者使用'[[$(date +%s)> $ e]]'(其中雙括號是重要的部分,儘管避免反引號並使用'$(...)'也是很好的建議,當在SO註釋中編寫shell腳本)。 – 2012-04-26 18:48:57

+0

...除了在這種情況下'''按字典順序排序而不是數字排序。所以,如果在你運行這個程序的時候,從這個紀元獲得一個數字以來的秒數(不可否認),那麼你會被洗掉;-) – wdebeaum 2012-04-26 18:55:12

+0

可能使用'time',這是一個buildin,而不是'date' , 幫幫我?我真的不明白腳本的作用,但似乎做了某種時機。 :) – 2012-04-26 18:55:42

0

我不確定你在做什麼$e,但是你可以使用shell內置的printf打印當前日期,你可以通過調用date來打印當前日期。子流程調用往往很昂貴。例如,如果您不在glibc2上,您可以執行以下操作:

printf '%(%+)T\n' -1 

準確獲取date命令的輸出。%+不支持在glibc2的,所以你可以構建的東西與其他參數相同,或者類似的東西:

printf '%(%c %Z)T\n' -1 

如果您需要捕獲和處理日期不知何故,那麼你可能還需要一個子shell調用使用$()但有一個不錯的機會,它仍然比date更快。