web-dev-qa-db-fra.com

Script Bash pour calculer le temps écoulé

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

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

J'imagine que ma logique est correcte, mais je termine avec l'impression suivante:

"Cela prend quelques secondes pour terminer cette tâche ..."

Quelque chose ne va pas avec mon évaluation de chaîne?

Je crois que les variables bash ne sont pas typées, j'adorerais s'il existe néanmoins une méthode "chaîne en entier" dans bash.

98
Michael Mao

$(()) ou $[] travaillera au calcul du résultat d'une opération arithmétique. Vous utilisez $() qui prend simplement la chaîne et l'évalue comme une commande. C'est un peu une distinction subtile. J'espère que cela t'aides.

Comme le remarque tink dans les commentaires sur cette réponse, $[] est obsolète et $(()) doit être privilégié.

72
OmnipotentEntity

Je trouve très propre d'utiliser la variable interne "$ SECONDS"

SECONDS=0 ; sleep 10 ; echo $SECONDS

123
Lon Kaut

Vous essayez d'exécuter le nombre dans la ENDTIME en tant que 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
49
perreal

Vous pouvez utiliser le mot clé time de Bash 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 référence dit à propos de TIMEFORMAT :

La valeur de ce paramètre est utilisée en tant que chaîne de format spécifiant la manière dont les informations de synchronisation des pipelines précédées du mot time reserved doivent être affichées. Le caractère "%" introduit une séquence d'échappement qui est étendue à une valeur temporelle ou à une autre information. Les séquences d'échappement et leur signification sont les suivantes: les accolades indiquent les portions optionnelles.

%%

    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 facultative p est un chiffre spécifiant la précision, le nombre de chiffres fractionnaires après un point décimal. Une valeur de 0 ne génère aucun point décimal ni fraction. Trois points au plus après la virgule peuvent être spécifiés. les valeurs de p supérieures à 3 sont remplacées par 3. Si p est non spécifié, la valeur 3 est utilisée.

Le paramètre optionnel l spécifie un format plus long, y compris les minutes, de la forme MMmSS.FFs. La valeur de p détermine si la 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 null, aucune information de minutage n'est affichée. Un retour à la ligne est ajouté lorsque la chaîne de format est affichée.

24
gniourf_gniourf

Essayez le code suivant:

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

essayez d'utiliser le temps avec l'option secondes écoulées:

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

ou \time -f%e sleep 1 en bash interactif.

voir la page de manuel time:

Les utilisateurs du shell bash doivent utiliser un chemin explicite pour exécuter la commande time externe et non la variante intégrée du shell. Sur le système où l'heure est installée dans/usr/bin, le premier exemple deviendrait/usr/bin/time wc/etc/hosts

et

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

Pour de plus grands nombres, nous voudrons peut-être imprimer dans un format plus lisible. L'exemple ci-dessous fait la même chose qu'un autre, mais imprime également au 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.

Pour utiliser un script comme décrit dans d’autres publications (point de départ de la capture, appelez la fonction avec l’heure de fin:

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