समय बीतने की गणना के लिए बैश स्क्रिप्ट


118

मैं अपने आदेशों के निष्पादन के लिए बीता समय की गणना करने के लिए बैश में एक स्क्रिप्ट लिख रहा हूं, विचार करें:

STARTTIME=$(date +%s)
#command block that takes time to complete...
#........
ENDTIME=$(date +%s)
echo "It takes $($ENDTIME - $STARTTIME) seconds to complete this task..."

मुझे लगता है कि मेरा तर्क सही है लेकिन मैं निम्नलिखित प्रिंट आउट के साथ समाप्त होता हूं:

"इस कार्य को पूरा करने में कुछ सेकंड लगते हैं ..."

मेरे स्ट्रिंग मूल्यांकन में कुछ भी गलत है?

मेरा मानना ​​है कि बैश वैरिएबल अनपेड हैं, मुझे पसंद होगा अगर बैश में "स्ट्रिंग टू पूर्णांक" विधि हो।

जवाबों:


83

या तो $(())या $[]अंकगणितीय आपरेशन के परिणाम की गणना के लिए काम करेंगे। आप उपयोग कर रहे हैं $()जो केवल स्ट्रिंग ले रहा है और इसे कमांड के रूप में मूल्यांकन कर रहा है। यह एक सूक्ष्म भेद है। उम्मीद है की यह मदद करेगा।

जैसा कि टिंक ने इस उत्तर पर टिप्पणियों में बताया है, $[]पदावनत किया जाता है, और $(())उसका पक्ष लिया जाना चाहिए।


7
आप उन दोनों को चारों ओर स्वैप करना चाह सकते हैं, जैसा कि बैश 4.x मैन-पेज बताता है कि $ [] पदावनत है और भविष्य के संस्करणों में हटा दिया जाएगा।
tink

2
धन्यवाद, मैं अनजान था।
ओमनीपोएंटेंटिटी

157

मुझे आंतरिक चर "$ SECONDS" का उपयोग करना बहुत साफ लगता है

SECONDS=0 ; sleep 10 ; echo $SECONDS


10
केवल सफलता =)
लोन कौट

1
सफलता की आवश्यकता, उपयोग तुम्हारा
Gromish

3
$SECONDSवास्तव में / बिन / बैश के लिए काम करता है। यह / बिन / डैश, डेबियन और उबंटू में डिफ़ॉल्ट शेल के लिए काम नहीं करता है।
कैमरन टैगगार्ट

2
इस समाधान के लिए नकारात्मक यह है कि यह केवल पूरे सेकंड को मापता है, अर्थात यदि आपको उप-सेकंड की सटीकता की आवश्यकता नहीं है तो यह उपयोगी नहीं है।
Czechnology

@Czechnology हाँ, यदि आप sleep 0.5ऊपर प्रयोग करते हैं, तो परिणाम कभी-कभी 0, कभी-कभी 1 (कम से कम बैश 5.0.3) होता है।
जर्नो

52

आप ENDTIMEकमांड के रूप में संख्या को निष्पादित करने का प्रयास कर रहे हैं । आपको एक त्रुटि भी दिखनी चाहिए 1370306857: command not found। इसके बजाय अंकगणितीय विस्तार का उपयोग करें :

echo "It takes $(($ENDTIME - $STARTTIME)) seconds to complete this task..."

आप कमांड को एक अलग स्क्रिप्ट में भी सहेज सकते हैं commands.sh, और टाइम कमांड का उपयोग कर सकते हैं:

time commands.sh

28

आप timeएक उपयुक्त प्रारूप स्ट्रिंग के साथ यहां बैश के कीवर्ड का उपयोग कर सकते हैं

TIMEFORMAT='It takes %R seconds to complete this task...'
time {
    #command block that takes time to complete...
    #........
 }

यहाँ संदर्भ के बारे मेंTIMEFORMAT क्या कहते हैं :

इस पैरामीटर का मान एक प्रारूप स्ट्रिंग के रूप में उपयोग किया जाता है, जिसमें निर्दिष्ट किया जाता है कि time आरक्षित शब्द के साथ उपसर्ग किए गए पाइपलाइनों की समय की जानकारी कैसे प्रदर्शित की जानी चाहिए। ' %' चरित्र एक भागने के क्रम का परिचय देता है जिसे एक समय मान या अन्य जानकारी में विस्तारित किया जाता है। भागने के क्रम और उनके अर्थ निम्नानुसार हैं; ब्रेसिज़ वैकल्पिक भागों को दर्शाते हैं।

%%

    A literal ‘%’.
%[p][l]R

    The elapsed time in seconds.
%[p][l]U

    The number of CPU seconds spent in user mode.
%[p][l]S

    The number of CPU seconds spent in system mode.
%P

    The CPU percentage, computed as (%U + %S) / %R. 

वैकल्पिक पी एक अंक है जो दशमलव को इंगित करने के बाद सटीक, भिन्नात्मक अंकों की संख्या को निर्दिष्ट करता है। 0 के मान का कोई दशमलव बिंदु या अंश आउटपुट नहीं होता है। दशमलव बिंदु के बाद अधिकतम तीन स्थानों पर निर्दिष्ट किया जा सकता है; 3 से अधिक p के मान 3 में बदल जाते हैं। यदि p निर्दिष्ट नहीं है, तो मान 3 का उपयोग किया जाता है।

वैकल्पिक MMMSS.FFs केl मिनटों सहित एक लंबा प्रारूप निर्दिष्ट करता है P का मान यह निर्धारित करता है कि अंश शामिल है या नहीं।

यदि यह वैरिएबल सेट नहीं है, तो बैश उस तरह से कार्य करता है जैसे कि उसका मूल्य था

$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'

यदि मान शून्य है, तो कोई समय जानकारी प्रदर्शित नहीं होती है। प्रारूप स्ट्रिंग प्रदर्शित होने पर एक अनुगामी न्यूलाइन जोड़ी जाती है।


10

बड़ी संख्या के लिए हम अधिक पठनीय प्रारूप में प्रिंट करना चाह सकते हैं। नीचे दिया गया उदाहरण अन्य के समान है, लेकिन "मानव" प्रारूप में भी प्रिंट करता है:

secs_to_human() {
    if [[ -z ${1} || ${1} -lt 60 ]] ;then
        min=0 ; secs="${1}"
    else
        time_mins=$(echo "scale=2; ${1}/60" | bc)
        min=$(echo ${time_mins} | cut -d'.' -f1)
        secs="0.$(echo ${time_mins} | cut -d'.' -f2)"
        secs=$(echo ${secs}*60|bc|awk '{print int($1+0.5)}')
    fi
    echo "Time Elapsed : ${min} minutes and ${secs} seconds."
}

सरल परीक्षण:

secs_to_human "300"
secs_to_human "305"
secs_to_human "59"
secs_to_human "60"
secs_to_human "660"
secs_to_human "3000"

आउटपुट:

Time Elapsed : 5 minutes and 0 seconds.
Time Elapsed : 5 minutes and 5 seconds.
Time Elapsed : 0 minutes and 59 seconds.
Time Elapsed : 1 minutes and 0 seconds.
Time Elapsed : 11 minutes and 0 seconds.
Time Elapsed : 50 minutes and 0 seconds.

अन्य पदों में वर्णित के रूप में एक स्क्रिप्ट में उपयोग करने के लिए (फिर शुरू बिंदु पर कब्जा) अंत समय के साथ समारोह कहते हैं:

start=$(date +%s)
# << performs some task here >>
secs_to_human "$(($(date +%s) - ${start}))"


5

यह माइक क्यू के फ़ंक्शन के लिए एक-लाइनर विकल्प है:

secs_to_human() {
    echo "$(( ${1} / 3600 ))h $(( (${1} / 60) % 60 ))m $(( ${1} % 60 ))s"
}

अच्छा! मैं आमतौर पर अपने बैश कोड के साथ बहुत क्रियाशील हूं, यह अच्छा है।
माइक क्यू

SECONDSलोन कौट के उत्तर से इसे जोड़ना और यह ध्यान रखना कि $ / $ {} अंकगणितीय चरों पर अनावश्यक है, कोड को इतना छोटा बना देता है कि इसे इनलाइन भी इस्तेमाल किया जा सके:echo "$((SECONDS/3600))h $(((SECONDS/60)%60))m $((SECONDS%60))s"
ssc

2

बीता हुआ सेकंड विकल्प के साथ समय का उपयोग करने का प्रयास करें:

/usr/bin/time -f%e sleep 1 दलदल के नीचे।

या \time -f%e sleep 1इंटरैक्टिव बैश में।

टाइम मैन पेज देखें:

बैश शेल के उपयोगकर्ताओं को बाहरी समय कमांड को चलाने के लिए एक स्पष्ट पथ का उपयोग करने की आवश्यकता है, न कि शेल बिल्ट वेरिएंट की। सिस्टम पर जहां समय / usr / bin में स्थापित है, पहला उदाहरण / usr / bin / time wc / etc / मेजबान बन जाएगा

तथा

FORMATTING THE OUTPUT
...
    %      A literal '%'.
    e      Elapsed  real  (wall  clock) time used by the process, in
                 seconds.

1
/bin/timeयहाँ काम करने नहीं जा रहा है: ओपी एक ब्लॉक का उल्लेख करता है । इसलिए हमें वास्तव में timeयहां कीवर्ड की जरूरत है।
ग्नौरफ_ग्निऑरफ

-3
start=$(date +%Y%m%d%H%M%S);
for x in {1..5};
do echo $x;
sleep 1; done;
end=$(date +%Y%m%d%H%M%S);
elapsed=$(($end-$start));
ftime=$(for((i=1;i<=$((${#end}-${#elapsed}));i++));
        do echo -n "-";
        done;
        echo ${elapsed});
echo -e "Start  : ${start}\nStop   : ${end}\nElapsed: ${ftime}"

Start  : 20171108005304
Stop   : 20171108005310
Elapsed: -------------6

-3
    #!/bin/bash

    time_elapsed(){
    appstop=$1; appstart=$2

    ss_strt=${appstart:12:2} ;ss_stop=${appstop:12:2}
    mm_strt=${appstart:10:2} ;mm_stop=${appstop:10:2}
     hh_strt=${appstart:8:2} ; hh_stop=${appstop:8:2}
     dd_strt=${appstart:6:2} ; dd_stop=${appstop:6:2}
     mh_strt=${appstart:4:2} ; mh_stop=${appstop:4:2}
     yy_strt=${appstart:0:4} ; yy_stop=${appstop:0:4}

    if [ "${ss_stop}" -lt "${ss_strt}" ]; then ss_stop=$((ss_stop+60)); mm_stop=$((mm_stop-1)); fi
    if [ "${mm_stop}" -lt "0" ]; then mm_stop=$((mm_stop+60)); hh_stop=$((hh_stop-1)); fi
    if [ "${mm_stop}" -lt "${mm_strt}" ]; then mm_stop=$((mm_stop+60)); hh_stop=$((hh_stop-1)); fi
    if [ "${hh_stop}" -lt "0" ]; then hh_stop=$((hh_stop+24)); dd_stop=$((dd_stop-1)); fi
    if [ "${hh_stop}" -lt "${hh_strt}" ]; then hh_stop=$((hh_stop+24)); dd_stop=$((dd_stop-1)); fi

    if [ "${dd_stop}" -lt "0" ]; then dd_stop=$((dd_stop+$(mh_days $mh_stop $yy_stop))); mh_stop=$((mh_stop-1)); fi
    if [ "${dd_stop}" -lt "${dd_strt}" ]; then dd_stop=$((dd_stop+$(mh_days $mh_stop $yy_stop))); mh_stop=$((mh_stop-1)); fi

    if [ "${mh_stop}" -lt "0" ]; then mh_stop=$((mh_stop+12)); yy_stop=$((yy_stop-1)); fi
    if [ "${mh_stop}" -lt "${mh_strt}" ]; then mh_stop=$((mh_stop+12)); yy_stop=$((yy_stop-1)); fi

    ss_espd=$((10#${ss_stop}-10#${ss_strt})); if [ "${#ss_espd}" -le "1" ]; then ss_espd=$(for((i=1;i<=$((${#ss_stop}-${#ss_espd}));i++)); do echo -n "0"; done; echo ${ss_espd}); fi
    mm_espd=$((10#${mm_stop}-10#${mm_strt})); if [ "${#mm_espd}" -le "1" ]; then mm_espd=$(for((i=1;i<=$((${#mm_stop}-${#mm_espd}));i++)); do echo -n "0"; done; echo ${mm_espd}); fi
    hh_espd=$((10#${hh_stop}-10#${hh_strt})); if [ "${#hh_espd}" -le "1" ]; then hh_espd=$(for((i=1;i<=$((${#hh_stop}-${#hh_espd}));i++)); do echo -n "0"; done; echo ${hh_espd}); fi
    dd_espd=$((10#${dd_stop}-10#${dd_strt})); if [ "${#dd_espd}" -le "1" ]; then dd_espd=$(for((i=1;i<=$((${#dd_stop}-${#dd_espd}));i++)); do echo -n "0"; done; echo ${dd_espd}); fi
    mh_espd=$((10#${mh_stop}-10#${mh_strt})); if [ "${#mh_espd}" -le "1" ]; then mh_espd=$(for((i=1;i<=$((${#mh_stop}-${#mh_espd}));i++)); do echo -n "0"; done; echo ${mh_espd}); fi
    yy_espd=$((10#${yy_stop}-10#${yy_strt})); if [ "${#yy_espd}" -le "1" ]; then yy_espd=$(for((i=1;i<=$((${#yy_stop}-${#yy_espd}));i++)); do echo -n "0"; done; echo ${yy_espd}); fi

    echo -e "${yy_espd}-${mh_espd}-${dd_espd} ${hh_espd}:${mm_espd}:${ss_espd}"
    #return $(echo -e "${yy_espd}-${mh_espd}-${dd_espd} ${hh_espd}:${mm_espd}:${ss_espd}")
    }

    mh_days(){
    mh_stop=$1; yy_stop=$2; #also checks if it's leap year or not

    case $mh_stop in
     [1,3,5,7,8,10,12]) mh_stop=31
     ;;
     2) (( !(yy_stop % 4) && (yy_stop % 100 || !(yy_stop % 400) ) )) && mh_stop=29 || mh_stop=28
     ;;
     [4,6,9,11]) mh_stop=30
     ;;
    esac

    return ${mh_stop}
    }

    appstart=$(date +%Y%m%d%H%M%S); read -p "Wait some time, then press nay-key..." key; appstop=$(date +%Y%m%d%H%M%S); elapsed=$(time_elapsed $appstop $appstart); echo -e "Start...: ${appstart:0:4}-${appstart:4:2}-${appstart:6:2} ${appstart:8:2}:${appstart:10:2}:${appstart:12:2}\nStop....: ${appstop:0:4}-${appstop:4:2}-${appstop:6:2} ${appstop:8:2}:${appstop:10:2}:${appstop:12:2}\n$(printf '%0.1s' "="{1..30})\nElapsed.: ${elapsed}"

    exit 0


-------------------------------------------- return
Wait some time, then press nay-key...
Start...: 2017-11-09 03:22:17
Stop....: 2017-11-09 03:22:18
==============================
Elapsed.: 0000-00-00 00:00:01
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.