Pytanie Skrypt Bash do obliczenia czasu, który upłynął


Piszę skrypt w bashu, aby obliczyć czas, jaki upłynął do wykonania moich poleceń, rozważ:

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

Domyślam się, że moja logika jest poprawna, ale kończę z następującym wydrukiem:

"Wykonanie tego zadania zajmuje kilka sekund ..."

Coś nie tak z moją oceną ciągów?

Uważam, że zmienne bash są bez typu, chciałbym, jeśli istnieje metoda "ciąg do liczby całkowitej" w bash.


76
2018-06-04 00:41


pochodzenie


@OnipotentEntity: czy możesz zrobić to jako odpowiedź? - Michael Mao
Jasne, Michael Mao. - OmnipotentEntity


Odpowiedzi:


Zarówno $(()) lub $[] będzie działał dla obliczenia wyniku operacji arytmetycznej. Używasz $() który po prostu bierze ciąg i ocenia go jako polecenie. To trochę subtelne rozróżnienie. Mam nadzieję że to pomoże.

Jak zauważył Tink w komentarzach dotyczących tej odpowiedzi, $[] jest przestarzałe, i $(()) powinno być faworyzowane.


58
2018-06-04 01:03



Możesz zamienić tych dwóch wokół, ponieważ bash 4.x strona man stwierdza, że $ [] jest przestarzałe i zostanie usunięte w przyszłych wersjach. - tink
Dziękuję, nie wiedziałem. - OmnipotentEntity


Uważam, że używanie wewnętrznej zmiennej "$ SECONDS" jest bardzo czyste.

SECONDS=0 ; sleep 10 ; echo $SECONDS


89
2017-07-27 21:51



cudowny, dest ma efekty uboczne? - g13013
Tylko sukces =) - Lon Kaut
Potrzebujesz sukcesu, użyj swojego - Gromish
$SECONDS rzeczywiście działa dla / bin / bash. Nie działa dla / bin / dash, domyślnej powłoki w Debianie i Ubuntu. - Cameron Taggart
Wadą tego rozwiązania jest to, że mierzy on tylko całe sekundy, tj. Nie nadaje się do użytku, jeśli potrzebna jest dokładność pod sekundę. - Czechnology


Próbujesz wykonać numer w ENDTIME jako polecenie. Powinieneś również zobaczyć błąd podobny 1370306857: command not found. Zamiast tego użyj rozszerzenie arytmetyczne:

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

Można również zapisać polecenia w osobnym skrypcie, commands.shi użyj polecenia czasu:

time commands.sh

43
2018-06-04 00:48





Możesz użyć Basha time słowo kluczowe z odpowiednim ciągiem formatującym

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

Oto, co odniesienie mówi TIMEFORMAT:

Wartość tego parametru jest używana jako ciąg formatujący określający sposób informacji o czasie dla potoków poprzedzonych znakiem time   zarezerwowane słowo powinno być wyświetlone. "%"Postać wprowadza   sekwencja escape, która jest rozwinięta do wartości czasu lub innych informacji.   Sekwencje specjalne i ich znaczenia są następujące; szelki   oznaczają opcjonalne części.

%%

    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. 

Opcjonalne str jest cyfrą określającą dokładność, liczbę cyfr ułamkowych po przecinku dziesiętnym. Wartość 0 powoduje brak   ułamek dziesiętny lub ułamek do wyprowadzenia. Co najwyżej trzy miejsca po   dziesiętny może być określony; wartości str więcej niż 3 są zmieniane   do 3. Jeśli str nie jest określony, używana jest wartość 3.

Opcjonalne l określa dłuższy format, w tym minuty MMmSS.FFs. Wartość str określa, czy   frakcja jest uwzględniona.

Jeśli ta zmienna nie jest ustawiona, Bash zachowuje się tak, jakby miała tę wartość

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

Jeśli wartość jest zerowa, informacja o taktowaniu nie jest wyświetlana. Końcowy znak nowej linii jest dodawany, gdy wyświetlany jest ciąg formatu.


21
2018-03-14 06:48





Spróbuj następującego kodu:

start=$(date +'%s') && sleep 5 && echo "It took $(($(date +'%s') - $start)) seconds"

5
2018-03-14 05:26





spróbuj użyć czasu z opcją upływających sekund:

/usr/bin/time -f%e sleep 1 pod bash.

lub \time -f%e sleep 1 w interaktywnym bashu.

zobacz stronę man man:

Użytkownicy powłoki bash muszą używać jawnej ścieżki do uruchomienia          zewnętrzne polecenie czasu, a nie wariant wbudowany powłoki. W systemie          gdzie czas jest zainstalowany w / usr / bin, pierwszy przykład stałby się               / usr / bin / time wc / etc / hosts

i

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

1
2018-06-04 01:59



/bin/time nie będzie tu działać: OP wspomina o blok. Więc naprawdę potrzebujemy słowa kluczowego time tutaj. - gniourf_gniourf


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

-1
2017-11-08 00:00





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

-1
2017-11-09 02:27