Je voudrais afficher lheure de fin dun script.
Ce que je fais actuellement est –
#!/bin/bash date ## echo the date at start # the script contents date ## echo the date at end
Ceci montre simplement lheure de début et de fin du script. Serait-ce possible dafficher une sortie à grain fin comme le temps processeur / temps io, etc?
Commentaires
- stackoverflow.com/questions/385408/ …
- Je pense que la réponse actuellement acceptée nest pas vraiment suffisante en raison des fluctuations temporelles.
- @CiroSantilli 烏坎 事件 2016 六四 事件 法轮功 Je pense que votre fil de discussion proposé nest toujours pas suffisant pour éliminer leffet des événements temporels.
- Aussi lié: stackoverflow.com/questions/5152858/… ou quelque peu unix.stackexchange.com/questions/334145 / …
- Il existe une commande que vous pouvez exécuter, puis elle chronomètre automatiquement toutes les commandes Unix, vous avez oublié comment lactiver?
Réponse
Jus t utilisez time
lorsque vous appelez le script:
time yourscript.sh
Commentaires
- Affiche trois fois:
real
,user
etsys
. Pour connaître leur signification, consultez ici . - et » real » est probablement ce que les gens veulent savoir – » Real est lheure de lhorloge murale – heure du début à la fin de lappel »
- Existe-t-il un moyen de capturer la sortie standard dans un fichier? Par exemple, quelque chose comme
time $( ... ) >> out.txt
- Vous pouvez également faire cela pour des séquences de commandes sur la ligne de commande, par exemple:
time (command1 && command2)
- Ou il pourrait, dans son script, simplement faire: echo $ SECONDS en supposant que cest bash ….
Réponse
Si time
nest « pas une option,
start=`date +%s` stuff end=`date +%s` runtime=$((end-start))
Commentaires
- Notez que cela ne fonctionne que si vous navez ‘ pas besoin dune précision inférieure à la seconde. Pour certaines utilisations, cela peut être acceptable , pour les autres non. Pour une précision légèrement meilleure (vous ‘ invoquez toujours
date
deux fois, par exemple, donc vous pouvez à mieux obtenir une précision à la milliseconde en pratique, et probablement moins), essayez dutiliserdate +%s.%N
. (%N
est en nanosecondes depuis toute la seconde .) - @ChrisH Oh. Cest bien de le signaler; le développement arithmétique de bash est uniquement composé dentiers. Je vois deux obvi ous options; soit abandonnez le point dans la chaîne de format de date (et traitez la valeur résultante comme des nanosecondes depuis lépoque), utilisez donc
date +%s%N
, ou utilisez quelque chose de plus capable commebc
pour calculer le temps dexécution réel à partir des deux valeurs comme le suggère jwchew. Pourtant, je pense que cette approche est une manière sous-optimale de le faire;time
est considérablement meilleur sil est disponible, pour les raisons exposées ci-dessus. - Installez simplement
bc
et procédez comme suit:runtime=$( echo "$end - $start" | bc -l )
- Si votre script prend plusieurs minutes, utilisez:
echo "Duration: $((($(date +%s)-$start)/60)) minutes
- Suite à @ rubo77 commentaire, si votre script prend plusieurs heures, utilisez
hours=$((runtime / 3600)); minutes=$(( (runtime % 3600) / 60 )); seconds=$(( (runtime % 3600) % 60 )); echo "Runtime: $hours:$minutes:$seconds (hh:mm:ss)"
Answer
Appelez simplement times
sans argument en quittant votre script.
Avec ksh
ou zsh
, vous pouvez également utiliser time
à la place. Avec zsh
, time
vous donnera également lheure de lhorloge murale en plus de l utilisateur et système temps CPU.
Pour conserver létat de sortie de votre script, vous pouvez le faire:
ret=$?; times; exit "$ret"
Ou vous peut également ajouter un piège sur EXIT
:
trap times EXIT
De cette façon, les heures seront appelées chaque fois que le shell sort et létat de sortie sera conservé.
$ bash -c "trap times EXIT; : {1..1000000}" 0m0.932s 0m0.028s 0m0.000s 0m0.000s $ zsh -c "trap time EXIT; : {1..1000000}" shell 0.67s user 0.01s system 100% cpu 0.677 total children 0.00s user 0.00s system 0% cpu 0.677 total
Notez également que tous les éléments bash
, ksh
et zsh
ont une variable spéciale $SECONDS
qui est automatiquement incrémentée toutes les secondes. À la fois dans zsh
et ksh93
, cette variable peut également être en virgule flottante (avec typeset -F SECONDS
) pour obtenir plus de précision. Ce nest que lheure de lhorloge murale, pas le temps CPU.
Commentaires
- Cette variable $ SECONDS est très utile, merci!
- Votre approche élimine-t-elle leffet des événements temporels? – – Je pense que votre approche est proche de lapproche
time
présentée précédemment.- – Je pense que lapprochetimeit
présentée en code MATLAB peut être utile ici. - Bonjour, @St é phane Chazelas. Jai trouvé que
times
‘ ne donne pas de temps sur le mur, nest-ce pas? par exemple,bash -c 'trap times EXIT;sleep 2'
- @Binarus, oui, cette fonctionnalité vient de ksh. Contrairement à ksh93 / zsh, à côté de bash ne prenant pas en charge la virgule flottante, il ‘ est également interrompu en ce quaprès avoir défini SECONDS sur 0, il passera à 1 de 0 à 1 seconde plus tard ( car il ne considère que le résultat de
time()
qui na quune seconde granularité complète). - @Binarus, pas que ‘ s entre 0 et 1. Si vous réglez SECONDS sur 0 à 12: 00: 00.000, il passera à 1 une seconde plus tard. Mais si vous le définissez sur 12: 00: 00.999, il passera à 1 un milliseconde plus tard. Mais oui, je conviens que cela n’a probablement pas ‘ d’importance en pratique si vous n’avez pas ‘ une précision inférieure à la seconde de toute façon.
Réponse
Je « suis un peu en retard dans le train en marche, mais je voulais publier ma solution (pour une précision inférieure à la seconde ) au cas où dautres tomberaient sur ce fil de discussion lors dune recherche. La sortie est au format jours, heures, minutes et enfin secondes:
res1=$(date +%s.%N) # do stuff in here res2=$(date +%s.%N) dt=$(echo "$res2 - $res1" | bc) dd=$(echo "$dt/86400" | bc) dt2=$(echo "$dt-86400*$dd" | bc) dh=$(echo "$dt2/3600" | bc) dt3=$(echo "$dt2-3600*$dh" | bc) dm=$(echo "$dt3/60" | bc) ds=$(echo "$dt3-60*$dm" | bc) LC_NUMERIC=C printf "Total runtime: %d:%02d:%02d:%02.4f\n" $dd $dh $dm $ds
Jespère que quelquun là-bas trouve cela utile!
Commentaires
- Je suppose quil ny a pas dautre moyen (seulement bash) sauf en utilisant ‘ bc ‘ pour faire les calculs. BTW vraiment bon script;)
- Attention à FreeBSD ‘ s
date
ne prend pas en charge la précision inférieure à la seconde et ajoutera simplement le littéral «N
» à lhorodatage. - Très beau script, mais mon bash ne le fait pas ‘ t gérer la sous-seconde partie. Jai aussi appris que / 1 dans bc supprime effectivement cela, alors jai ajouté @ / 1 @ au calcul $ ds, et il affiche des trucs très bien maintenant!
- bc prend en charge modulo:
dt2=$(echo "$dt%86400" | bc)
. Dire simplement … BTW, je préfère la formedt2=$(bc <<< "${dt}%86400")
mais que ‘ est entièrement personnel. - Je ne ‘ Je ne sais encore rien sur
bc
, mais la division par86400
me rend méfiant pour le raison suivante: il y a des jours qui nont pas 86400 secondes, par exemple des jours où lheure passe de lheure dété à lheure normale et vice versa, ou des jours avec des secondes intercalaires. Si ces jours font partie de la période que vous souhaitez calculer, cest-à-dire se situent entreres1
etres2
(y compris ces valeurs), votre script échouera probablement.
Réponse
Ma méthode pour bash
:
# Reset BASH time counter SECONDS=0 # # do stuff # ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
Commentaires
- Cela montre le temps écoulé, mais cela ne ‘ t afficher » une sortie à grain fin comme le temps du processeur, le temps dE / S » comme demandé dans la question.
- Ceux qui recherchent une réponse à la question posée trouveront probablement cette solution utile. Votre commentaire serait mieux adressé à la question des OP.
Réponse
Personnellement, jaime envelopper tous mes code de script dans une fonction « main » comme ceci:
main () { echo running ... } # stuff ... # calling the function at the very end of the script time main
Remarquez à quel point il est facile dutiliser la commande time
dans ce scénario. Évidemment, vous ne mesurez pas le temps précis, y compris le temps d’analyse du script, mais je le trouve suffisamment précis dans la plupart des situations.
Commentaires
- Excellente solution, ne ‘ t nécessite des outils supplémentaires et est autonome.
Réponse
#!/bin/bash start=$(date +%s.%N) # HERE BE CODE end=$(date +%s.%N) runtime=$(python -c "print(${end} - ${start})") echo "Runtime was $runtime"
Oui, cela appelle Python, mais si vous pouvez vivre avec cela, alors cest une solution assez intéressante et concise.
Commentaires
- Sachez que lexécution de cette commande
python
dans un sous-shell et la lecture de sa sortie prendront plusieurs millions de nanosecondes sur la plupart des systèmes actuels. Idem pour lexécution dedate
. - » Plusieurs millions de nanosecondes » font plusieurs millisecondes . Les gens qui chronométrent les scripts bash ne sont généralement pas très préoccupés par cela (sauf sils exécutent plusieurs milliards de scripts par mégaseconde).
- Notez également que, même si le le calcul est fait dans un processus python, les valeurs ont été entièrement collectées avant lappel de python. Le temps dexécution du script sera mesuré correctement, sans les » millions de nanosecondes » surcoût.
-
time main
ci-dessus est tellement plus propre …oui, nous pouvons vivre avec beaucoup de dégradation, mais cela ‘ est bien mieux sans alors laissez ‘ rester des ingénieurs! -
$(echo $end - $start | bc)
fera la même chose sans python
Réponse
Cette question est assez ancienne, mais en essayant de trouver ma façon préférée de le faire, ce fil est venu haut … et je « suis surpris que personne ne lait mentionné:
perf stat -r 10 -B sleep 1
« perf » est un outil danalyse des performances inclus dans le noyau sous « tools / perf » et souvent disponible pour linstallation en tant que paquet séparé (« perf » dans CentOS et « linux-tools » sur Debian / Ubuntu). Le Linux Kernal perf Wiki a beaucoup plus dinformations à ce sujet.
Lexécution de « perf stat » donne pas mal de détails, y compris le temps dexécution moyen à la fin:
1.002248382 seconds time elapsed ( +- 0.01% )
Commentaires
- Quest-ce que
perf
? - @B Layer – a modifié ma réponse t o donne une brève description de ‘ perf ‘.
-
perf stat
se plaint maintenant de » Vous navez peut-être pas lautorisation de collecter des statistiques. » sauf si vous exécutez certaines commandes avecsudo
, ce qui le rend inutile dans tous les scénarios où vous ne possédez ‘ pas complètement la machine cible. - Incroyable, merci! Solution bien plus fine que
time
dautres suggèrent. En particulier,time
ne sapplique pas à la mesure des solutions de concurrence de code (car il ne permet pas ‘ t le temps dimpression en millisecondes et moins) , contrairement à votre solution.
Réponse
Une petite fonction shell qui peut être ajoutée avant commandes pour mesurer leur temps:
tm() { local start=$(date +%s) $@ local exit_code=$? echo >&2 "took ~$(($(date +%s)-${start})) seconds. exited with ${exit_code}" return $exit_code }
Ensuite, utilisez-le dans votre script, ou sur votre ligne de commande comme ceci:
tm the_original_command with all its parameters
Commentaires
- Cela vaudrait la peine dajouter des millisecondes, a essayé ilke
s=$(date +%s000)
, pas sûr si cela fonctionne. - @loretoparisi pendant des millisecondes, vous pouvez essayer
date +%s%N
. Voir serverfault.com/questions/151109/… - Cest génial, mais plus sûr utilisez
"$@"
Answer
#!/bin/csh #PBS -q glean #PBS -l nodes=1:ppn=1 #PBS -l walltime=10:00:00 #PBS -o a.log #PBS -e a.err #PBS -V #PBS -M [email protected] #PBS -m abe #PBS -A k4zhang-group START=$(date +%s) for i in {1..1000000} do echo 1 done END=$(date +%s) DIFF=$(echo "$END - $START" | bc) echo "It takes DIFF=$DIFF seconds to complete this task..."
Commentaires
- En quoi est-ce vraiment différent des autres réponses déjà données qui utilisent
date
avant et après le script et afficher la différence entre eux?
Réponse
-
Juste utilisez
time [any command]
. Ex:time sleep 1
dormira pendant un temps réel (cest-à-dire: comme chronométré par un chronomètre) de ~ 1.000 à ~ 1.020 sec, comme indiqué ici:$ time sleep 1 real 0m1.011s user 0m0.004s sys 0m0.000s
Quelle belle chose. Vous pouvez mettre nimporte quelle commande après, et il produit le résultat sous une forme agréable et lisible par lhomme. Jaime vraiment lutiliser pour chronométrer les builds. Ex:
# time your "make" build time make # time your "Bazel" build time bazel build //path/to/some:target
… ou pour des opérations git qui peuvent potentiellement être long, pour que je puisse développer des attentes mentales réalistes:
# time how long it takes to pull from a massive repo when # I"m working from home during COVID-19. NB: `git pull` # is sooooo much slower than just pulling the one branch # you need with `git pull origin <branch>`, so just fetch # or pull what you need! time git pull origin master
-
Pour des besoins de synchronisation plus personnalisés où vous devrez peut-être manipuler la sortie ou la convertir en dautres formes, en bash , utilisez la variable interne
$SECONDS
. Voici « une démo, comprenant la conversion de ces secondes en dautres unités, telles que les minutes en virgule flottante:Notez que
dt_min
est arrondi de0.01666666666...
(1 seconde = autant de minutes) à0.017
dans ce cas puisque je « m utilise la fonctionprintf
pour arrondir. La partiesleep 1;
ci-dessous est lendroit où vous « appelleriez votre script pour quil sexécute et chronométrer, mais je dors juste 1 seconde pour le plaisir de cette démo.Commande:
start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); \ dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); \ echo "dt_sec = $dt_sec; dt_min = $dt_min"
Sortie:
dt_sec = 1; dt_min = 0.017
Connexes:
- En savoir plus à propos de
bc
etprintf
dans ma réponse ici: https://stackoverflow.com/questions/12722095/how-do-i-use-floating-point-division-in-bash/58479867#58479867 - Je ne me souviens plus de lendroit où jai découvert la commande
time
, mais cela peut provenir de Réponse de @Trudbert « ici .
Réponse
En utilisant uniquement bash il est également possible de mesurer et de calculer la durée dune partie du script shell (ou le temps écoulé pour tout le script):
start=$SECONDS ... # do time consuming stuff end=$SECONDS
vous pouvez maintenant soit simplement imprimer la différence:
echo "duration: $((end-start)) seconds."
si vous navez besoin que dune durée incrémentielle, faites:
echo "duration: $((SECONDS-start)) seconds elapsed.."
Vous pouvez également stocker la durée dans une variable:
let diff=end-start
Commentaires
- ^ CECI est la réponse aux gens. Ou plus simplement: $ SECONDS à la fin. Il ‘ est une variable Bash INTÉGRÉE. Toutes les autres réponses font juste un travail supplémentaire pour réinventer cette roue …
- Ceci est juste une répétition de la réponse précédente de Marks unix.stackexchange .com / a / 340156/155362 .
Answer
Fonction de chronométrage basée sur SECONDS
, limité à la granularité de second niveau uniquement, nutilise aucune commande externe:
time_it() { local start=$SECONDS ts ec printf -v ts "%(%Y-%m-%d_%H:%M:%S)T" -1 printf "%s\n" "$ts Starting $*" "$@"; ec=$? printf -v ts "%(%Y-%m-%d_%H:%M:%S)T" -1 printf "%s\n" "$ts Finished $*; elapsed = $((SECONDS-start)) seconds" # make sure to return the exit code of the command so that the caller can use it return "$ec" }
Par exemple:
time_it sleep 5
donne
2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished sleep 5; elapsed = 5 seconds
Réponse
Utiliser le temps bash intégré?
time: time [-p] PIPELINE Execute PIPELINE and print a summary of the real time, user CPU time, and system CPU time spent executing PIPELINE when it terminates. The return status is the return status of PIPELINE. The `-p" option prints the timing summary in a slightly different format. This uses the value of the TIMEFORMAT variable as the output format.
Exemple:
TIMEFORMAT="The command took %Rs" time { sleep 0.1 }
Résultat:
The command took 0.108s
Answer
Voici « une variante dAlex « La réponse. Je ne me soucie que des minutes et des secondes, mais je voulais aussi quelle soit formatée différemment. Jai donc fait ceci:
start=$(date +%s) end=$(date +%s) runtime=$(python -c "print "%u:%02u" % ((${end} - ${start})/60, (${end} - ${start})%60)")
Commentaires
- Pourquoi voter contre? Ai-je un bug?
- Utiliser
python
pour ce calcul me semble non plus être un bogue, désolé mec. Pourquoi les gens peuvent ‘ appeler simplementtime
me dépasse.
Réponse
#!/bin/bash begin=$(date +"%s") Script termin=$(date +"%s") difftimelps=$(($termin-$begin)) echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution."
Réponse
La solution acceptée en utilisant time
écrit dans stderr
.
La solution utilisant times
écrit dans stdout
.
Les solutions utilisant $SECONDS
manquent de précision inférieure à la seconde.
Les autres solutions impliquent lappel de programmes externes comme date
ou perf
ce qui nest pas efficace.
Si lun de ces éléments vous convient, utilisez-le.
Mais si vous avez besoin dune solution efficace pour obtenir les temps avec une précision de la milliseconde et en ont besoin en variables telles que la sortie dorigine reste intacte vous pouvez combiner la substitution de processus avec des redirections autour de time
, ce qui est beaucoup plus rapide que dappeler programmes externes et autorise les redirections autour du script dencapsulation de synchronisation comme sur la commande / script dorigine.
# Preparations: Cmd=vgs # example of a program to be timed which is writing to stdout and stderr Cmd="eval { echo stdout; echo stderr >&2; sleep 0.1; }" # other example; replace with your own TIMEFORMAT="%3R %3U %3S" # make time output easy to parse
Sélectionnez lune des variantes suivantes analysant la sortie de time
adapté à vos besoins:
Variante la plus courte où stdout
de $Cmd
est écrit dans stderr
et rien à stdout
:
read Elapsed User System < <({ time $Cmd 2>&3; } 3>&2 2>&1 >&3)
Variante plus longue qui conserve original stdout
et stderr
séparés lun de lautre:
{ read Elapsed User System < <({ time $Cmd 2>&4; } 4>&2 2>&1 >&3); } 3>&1
La variante la plus compliquée comprend la fermeture des descripteurs de fichiers supplémentaires tels que $Cmd
est appelé comme si sans ce wrapper de synchronisation et lvm
Les commandes comme vgs
ne se plaignent pas de la fuite de descripteurs de fichiers:
{ read Elapsed User System < <({ time $Cmd 2>&4 4>&-; } 4>&2 2>&1 >&3 3>&-); } 3>&1
Vous peut même simuler une addition en virgule flottante dans bash
sans appeler bc
ce qui serait beaucoup plus lent:
CPU=`printf %04d $((10#${User/.}+10#${System/.}))` # replace with your own postprocessing echo CPU ${CPU::-3}.${CPU: -3} s, Elapsed $Elapsed s >&2 # redirected independent of $Cmd
Sorties possibles avec les deux exemples de $Cmd
sur un CPU lent:
File descriptor 3 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash File descriptor 4 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash VG #PV #LV #SN Attr VSize VFree b3 3 24 0 wz--n- 1.31t 1.19t CPU 0.052 s, Elapsed 0.056 s
Ou:
stdout stderr CPU 0.008 s, Elapsed 0.109 s