153 votes

Bash script pour calculer le temps écoulé

J'écris un script en bash pour calculer le temps écoulé pour l'exécution de mes commandes, considérer :

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

Je suppose que ma logique est correcte, mais je me retrouve avec l'impression suivante :

"Il faut quelques secondes pour accomplir cette tâche..."

Quelque chose ne va pas dans mon évaluation des chaînes de caractères ?

Je crois que les variables bash ne sont pas typées, j'adorerais qu'il y ait une méthode "string to integer" dans bash néanmoins.

0 votes

FYI : unix.stackexchange.com a une question plus générique sur ce sujet (mesurer le temps elliptique dans bash), voir : unix.stackexchange.com/questions/314365

210voto

Lon Kaut Points 2001

Je trouve très propre l'utilisation de la variable interne "$SECONDS".

SECONDS=0 ; sleep 10 ; echo $SECONDS

4 votes

$SECONDS fonctionne en effet pour /bin/bash. Il ne fonctionne pas pour le /bin/dash, l'interpréteur de commandes par défaut dans Debian et Ubuntu.

2 votes

L'inconvénient de cette solution est qu'elle ne mesure que des secondes entières, c'est-à-dire qu'elle n'est pas utilisable si vous avez besoin d'une précision inférieure à la seconde.

0 votes

@Czechnology oui, si vous utilisez sleep 0.5 dans l'exemple ci-dessus, le résultat est parfois 0, parfois 1 (au moins avec Bash 5.0.3).

92voto

OmnipotentEntity Points 7083

Soit $(()) o $[] fonctionnera pour calculer le résultat d'une opération arithmétique. Vous utilisez $() qui prend simplement la chaîne et l'évalue comme une commande. C'est une distinction un peu subtile. J'espère que cela vous aidera.

Comme l'a souligné Tink dans les commentaires de cette réponse, $[] est déprécié, et $(()) devrait être favorisée.

7 votes

Vous voudrez peut-être intervertir ces deux éléments, car la page de manuel de bash 4.x indique que l'option $[] est déprécié et sera supprimé dans les prochaines versions.

61voto

perreal Points 47912

Vous essayez d'exécuter le numéro dans la section ENDTIME comme une commande. Vous devriez également voir une erreur comme 1370306857: command not found . Utilisez plutôt le expansion arithmétique :

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

Vous pouvez également enregistrer les commandes dans un script distinct, commands.sh et utiliser la commande time :

time commands.sh

36voto

gniourf_gniourf Points 9393

Vous pouvez utiliser la fonction time ici avec une chaîne de format appropriée

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

Voici ce que le TIMEFORMAT :

La valeur de ce paramètre est utilisée comme chaîne de format spécifiant la manière dont les informations de synchronisation pour les pipelines préfixés par le préfixe time Le mot réservé doit être affiché. Le mot ' % Le personnage de l'article introduit un qui est étendue à une valeur temporelle ou à d'autres informations. Les séquences d'échappement et leurs significations sont les suivantes ; les accolades indiquent les parties facultatives.

%%

    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. 

L'option p est un chiffre spécifiant la précision, c'est-à-dire le nombre de chiffres fractionnaires après le point décimal. Une valeur de 0 n'entraîne pas décimale ou de fraction. On peut spécifier au maximum trois positions après la peut être spécifié ; les valeurs de p supérieures à 3 sont modifiées à 3. Si p n'est pas spécifié, la valeur 3 est utilisée.

L'option l spécifie un format plus long, incluant les minutes, de la forme MMmSS.FFs. La valeur de p détermine si le fraction est incluse ou non.

Si cette variable n'est pas définie, Bash agit comme si elle avait la valeur

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

Si la valeur est nulle, aucune information sur le calendrier n'est affichée. Une nouvelle ligne de queue est ajoutée lorsque la chaîne de format est affichée.

0 votes

Si vous devez inclure des caractères antislash dans la variable TIMEFORMAT, vous devez utiliser un $ au début. Par exemple, TIMEFORMAT=' \nreal : %3R' ne fonctionnera pas, alors que TIMEFORMAT=$' \nreal : %3R' le fera. La réponse implique bien sûr cela, je voulais juste le rendre plus explicite.

0 votes

@blaze9 Bien sûr, ça s'appelle Citations ANSI-C et son utilisation n'est pas limitée à TIMEFORMAT vous pouvez l'utiliser chaque fois que vous voulez inclure un échappement de backslash dans une chaîne de caractères. Par exemple a=$'hello\nworld' et ensuite echo "$a" .

19voto

Mike Q Points 461

Pour les grands nombres, nous pouvons souhaiter imprimer dans un format plus lisible. L'exemple ci-dessous fait la même chose que l'autre mais imprime également dans un format "humain" :

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."
}

Test simple :

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

Sortie :

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.

A utiliser dans un script comme décrit dans d'autres posts (capture du point de départ puis appel de la fonction avec l'heure d'arrivée :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X