2009-04-11 11 views
17

Comment puis-je écrire un script pour calculer le temps que le script a pris pour terminer?Combien de temps un fichier batch doit-il exécuter?

Je pensais que ce serait le cas, mais évidemment pas ..

@echo off 
set starttime=%time% 
set endtime=%time% 

REM do stuff here 

set /a runtime=%endtime%-%starttime% 
echo Script took %runtime% to complete 
+1

shouldn » t vous définissez la fin après avoir fait quelques trucs? est-ce une faute de frappe? –

+0

bien, vous pouvez simplement faire "time ./myscript" – mpen

+0

@mark, dans une installation Windows stock, l'heure est une commande intégrée dans CMD.EXE qui définit ou affiche l'heure actuelle. – RBerteig

Répondre

1

Vous ne pouvez pas faire directement l'arithmétique de temps dans les scripts de traitement par lots, de sorte que vous aurez soit besoin d'un programme externe pour calculer la différence de temps , ou extraire chaque partie du temps et faire de l'arithmétique de cette façon.

Jetez un oeil à la fin de this forum thread pour un exemple de la façon de faire ce dernier. Je suppose également que c'est une faute de frappe, mais vous voulez être sûr de régler endtimeaprès traitement.

2

Ma préférence personnelle est d'installer Cygwin et utilisez la commande time mais, si vous avez réellement avez de le faire en tant que fichier de commandes, vous ne pouvez pas soustraire seulement les cordes, il faut les traiter comme des parties.

Le script suivant chronométrera une commande Ping de 10 secondes avec la possibilité de franchir une limite d'une seule journée sans être liée par des nombres négatifs. Une légère amélioration lui permettrait de franchir de nombreuses frontières.

@echo off 
setlocal enableextensions enabledelayedexpansion 
set starttime=%time% 
ping -n 11 127.0.0.1 >nul: 2>nul: 
set endtime=%time% 

set /a hrs=%endtime:~0,2% 
set /a hrs=%hrs%-%starttime:~0,2% 

set /a mins=%endtime:~3,2% 
set /a mins=%mins%-%starttime:~3,2% 

set /a secs=%endtime:~6,2% 
set /a secs=%secs%-%starttime:~6,2% 

if %secs% lss 0 (
    set /a secs=!secs!+60 
    set /a mins=!mins!-1 
) 
if %mins% lss 0 (
    set /a mins=!mins!+60 
    set /a hrs=!hrs!-1 
) 
if %hrs% lss 0 (
    set /a hrs=!hrs!+24 
) 
set /a tot=%secs%+%mins%*60+%hrs%*3600 

echo End  = %endtime% 
echo Start = %starttime% 
echo Hours = %hrs% 
echo Minutes = %mins% 
echo Seconds = %secs% 
echo Total = %tot% 

endlocal 
4

Ceci est un peu tangentiel, mais cela peut vous aider.

Microsoft a un programme timeit.exe qui fonctionne plus ou moins comme une version améliorée de la commande unix 'time'. Il vient dans le Windows Server 2003 Resource Kit, et il a pratiquement remplacé toutes les fois où j'ai voulu faire quelque chose comme ce que vous suggérez.

Cela peut valoir le coup d'oeil.

35

Deux choses sautent sur le fichier de commandes d'origine. mais ni l'un ni l'autre ne va aider à long terme.

  1. Quelle que soit votre méthode de référence, assurez-vous de saisir l'heure de début avant l'opération, et l'heure de fin après l'opération. Votre échantillon ne le fait pas.

  2. %time% évalue à quelque chose comme "12: 34: 56.78", et la commande SET /A ne peut pas les soustraire. Vous avez besoin d'une commande qui produit un horodatage scalaire simple.

J'allais dire qu'il ne peut pas être fait, mais la langue de lot est beaucoup plus puissant que lui donne crédit, voici donc une implémentation simple de TIMER.BAT. Pour mémoire, Pax m'a battu à une réponse montrant la division de la chaîne alors que je bidouiller, et Johannes Rössel a suggéré de déplacer l'arithmétique en dehors de la région mesurée:

@echo off 
setlocal 

rem Remeber start time. Note that we don't look at the date, so this 
rem calculation won't work right if the program run spans local midnight. 
set t0=%time: =0% 

rem do something here.... but probably with more care about quoting. 
rem specifically, odd things will happen if any arguments contain 
rem precent signs or carets and there may be no way to prevent it. 
%* 

rem Capture the end time before doing anything else 
set t=%time: =0% 

rem make t0 into a scaler in 100ths of a second, being careful not 
rem to let SET/A misinterpret 08 and 09 as octal 
set /a h=1%t0:~0,2%-100 
set /a m=1%t0:~3,2%-100 
set /a s=1%t0:~6,2%-100 
set /a c=1%t0:~9,2%-100 
set /a starttime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c% 

rem make t into a scaler in 100ths of a second 
set /a h=1%t:~0,2%-100 
set /a m=1%t:~3,2%-100 
set /a s=1%t:~6,2%-100 
set /a c=1%t:~9,2%-100 
set /a endtime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c% 

rem runtime in 100ths is now just end - start 
set /a runtime = %endtime% - %starttime% 
set runtime = %s%.%c% 

echo Started at %t0% 
echo Ran for %runtime%0 ms 

Vous pouvez simplifier l'arithmétique et être un peu plus honnête au sujet de la précision globale de ceci en ne dérangeant pas avec les centièmes d'une deuxième partie.Ici, il est en action, en supposant que vous avez une commande de sommeil ou d'une autre perte de temps:

C:> TIMER SLEEP 3 
Script took 3000 ms to complete 
C:> 

Edit: Je révisé le code et sa description comme suggéré dans un commentaire.

Je pense que lorsque l'équipe NT a remplacé COMMAND.COM avec CMD.EXE, ils ont pensé qu'ils ne s'en tireraient pas en le rendant très différent. Mais en réalité, c'est presque une langue entièrement nouvelle. La plupart des anciennes commandes favorites ont de nouvelles fonctionnalités si les extensions sont activées.

L'un d'entre eux est SETLOCAL qui empêche les variables de modifier l'environnement de l'appelant. Un autre est SET /A qui vous donne une quantité remarquable d'arithmétique. L'astuce principale que j'ai utilisée ici est la nouvelle syntaxe d'extraction de sous-chaîne où %t:~3,2% signifie les deux caractères commençant à l'offset 3 dans la valeur de la variable nommée t. Pour un vrai shocker, jetez un oeil à la description complète de set (essayez SET /? à une invite) et si cela ne vous effraie pas, regardez FOR /? et notez qu'il peut analyser le texte à partir de fichiers ...

Edit 2: mauvaise manipulation de champs fixes de temps contenant 08 ou 09 rapporté par Frankie dans les commentaires. Tweaked quelques choses, et ajouté quelques commentaires.

Notez qu'il y a un oubli flagrant ici que je ne vais probablement pas résoudre. Cela ne fonctionnera pas si la commande commence un jour différent de la fin. C'est-à-dire, il va faire quelques calculs liés à l'heure de la journée et signaler une différence, mais la différence ne veut pas dire grand-chose. Il est facile de le fixer pour au moins prévenir de ce cas. La fixer pour faire la bonne chose est plus difficile.

Édition 3: Correction d'une erreur où% h% n'est pas défini correctement pour les heures à un chiffre. Cela est dû au% time% retournant "9: 01: 23.45". Remarquez l'espace. En utilisant% time: = 0% remplace l'espace par un zéro et% h% sera défini correctement. Cette erreur ne s'est produite que lorsqu'un script s'est déroulé d'une heure à l'autre.

+0

+1 pour aller plus loin ... pouvez-vous expliquer le set/a business (démarré sous Linux actuellement) – ojblass

+0

set/a fait de l'arithmétique dans Batch. Ce qu'il fait ici, c'est tout réduire à 1/100 de seconde. Ensuite, vous pouvez simplement les soustraire, car ils sont tous deux juste des chiffres. – Joey

+0

Vous voudrez peut-être faire tout le calcul après que votre commande soit exécutée, bien que ... math dans cmd ne soit pas exactement rapide, alors stockez l'heure de début et manipulez-la après que votre commande soit terminée pour qu'elle ne soit pas comptée l'heure de la commande. Dunno si cela fait une différence, apparemment pas – Joey

2

Vérifiez ce script qui récupérera l'heure via WMI afin que son paramètre régional soit indépendant.

@echo off 
:::::::::::::::::::::::::::::::::::::::::: 
::  TimeDiff v1.00 by LEVENTE ROG       :: 
::       www.thesysadminhimself.com     :: 
:::::::::::::::::::::::::::::::::::::::::: 
  
::[ EULA ]::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
::  Feel free to use this script. The code can be redistributed  :: 
::  and edited, but please keep the credits.                     :: 
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
  
::[ CHANGELOG ]:::::::::::::: 
::  v1.00 - First Version  :: 
::::::::::::::::::::::::::::: 
  
  
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO (
 set Milisecond=%time:~9,2% 
 set Day=%%A 
 set Hour=%%B 
 set Minute=%%C 
 set Second=%%D 
) 
set /a Start=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100+%Milisecond% 
  
:: 
:: 
:: PUT COMMANDS HERE 
ping www.thesysadminhimself.com 
:: 
:: 
  
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."') DO (
 set Day=%%A 
 set Hour=%%B 
 set Minute=%%C 
 set Second=%%D 
) 
set Milisecond=%time:~9,2% 
set /a End=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100+%Milisecond% 
set /a Diff=%End%-%Start% 
set /a DiffMS=%Diff%%%100 
set /a Diff=(%Diff%-%DiffMS%)/100 
set /a DiffSec=%Diff%%%60 
set /a Diff=(%Diff%-%Diff%%%60)/60 
set /a DiffMin=%Diff%%%60 
set /a Diff=(%Diff%-%Diff%%%60)/60 
set /a DiffHrs=%Diff% 
  
:: format with leading zeroes 
if %DiffMS% LSS 10 set DiffMS=0%DiffMS!% 
if %DiffSec% LSS 10 set DiffMS=0%DiffSec% 
if %DiffMin% LSS 10 set DiffMS=0%DiffMin% 
if %DiffHrs% LSS 10 set DiffMS=0%DiffHrs% 
  
echo %DiffHrs%:%DiffMin%:%DiffSec%.%DiffMS% 
+0

+1 belle solution, mais il est lent, chaque horodatage a besoin de ~ 100ms-200ms (sur mon pc 2.4GHz Core2 Duo) – jeb

3

Excellente petite routine. Cependant, si le calcul s'étend sur deux jours, le calcul est incorrect. Le résultat doit être soustrait de 24 heures (8640000 centisecondes).

Supprimez également l'une des commandes 'set' en double dans la ligne correspondante.

Notez que les paramètres régionaux affectent le format de la fonction TIME, la valeur décimale étant une valeur maximale au Royaume-Uni plutôt qu'une virgule.

Les lignes

rem on aurait pu mesuré le temps jours inbetween

if %ENDTIME% LSS %STARTTIME% set set /A DURATION=%STARTTIME%-%ENDTIME% 

besoin de changer de

rem nous aurions pu mesurer le temps au fil des jours

if %ENDTIME% LSS %STARTTIME% set /A DURATION=8640000 - (%STARTTIME% - %ENDTIME%) 
Questions connexes