sleep en scripts de Windows. Operaciones aritméticas en CMD. Comandos para scripting del ResKit.
En Ejemplos de scripting en Windows: Añadir la fecha y la hora al nombre de un fichero estuvimos viendo algunas indicaciones para hacer scripts en Windows algo más sofisticados de lo habitual.
Siguiendo un poco con la temática de hacer scripts o ficheros batch en Windows, hace unos días me encontré con el problema de que en Windows por defecto no hay un comando sleep
como en los sistemas UNIX. Googleando, encontré la página Batch file SLEEP Command que explica que en las Windows Server 2003 Resource Kit Tools hay un sleep.exe
. Sin embargo, es posible que queramos hacer un script portable que podamos ejecutar en cualquier sistema sin necesidad de tener que instalar o copiar nada adicional. Incluso puede haber situaciones en las que simplemente resulte imposible descargar el Resource Kit o copiarlo de otro sistema y realmente necesitemos una especie de sleep
en nuestro script. Pues bien, la página Implementing the WAIT Command in a Batch File nos hace una sugerencia que me ha gustado mucho basada en el comando ping
de Windows, que por defecto (y no se puede cambiar) manda un paquete ICMP por segundo.
Con algunas pequeñas modificaciones de cosecha propia, el sleep.bat
basado en ping
quedaría así:
@echo off set /a i=%1%+1 ping 127.0.0.1 -n %i% -w 1000 > nul
y lo usaríamos en nuestro script con una línea como:
call sleep 10
donde en lugar de 10 pondríamos el número de segundos que queremos esperar.
Como el ping
de Windows espera un segundo entre cada dos paquetes mandados, para esperar n segundos, necesitaremos enviar n+1 paquetes. De ahí la operación aritmética del “set /a
“. Por supuesto, podemos ahorrarnos tener que andar con dos ficheros batch metiendo directamente el ping
en el script final.
Este método es unos milisegundos impreciso, en función de lo que tarde el ping
en ejecutarse y lo que tarde la IP interna en contestar, aunque la imprecisión debería ser aceptable para la mayoría de los casos.
Respecto al “set /a
” que he usado para sumar , se trata de una interesante forma de ejecutar operaciones aritméticas con enteros de 32 bits con signo en el CMD de Windows:
C:\>set /a (2+3)*4 20 C:\>set /a 7/2 3 C:\>set /a 7%2 1
Esto lo encontramos documentado en la salida del “set /?
“:
Two new switches have been added to the SET command: SET /A expression SET /P variable=[promptString] The /A switch specifies that the string to the right of the equal sign is a numerical expression that is evaluated. The expression evaluator is pretty simple and supports the following operations, in decreasing order of precedence: () - grouping ! ~ - - unary operators * / % - arithmetic operators + - - arithmetic operators << >> - logical shift & - bitwise and ^ - bitwise exclusive or | - bitwise or = *= /= %= += -= - assignment &= ^= |= <<= >>= , - expression separator If you use any of the logical or modulus operators, you will need to enclose the expression string in quotes. Any non-numeric strings in the expression are treated as environment variable names whose values are converted to numbers before using them. If an environment variable name is specified but is not defined in the current environment, then a value of zero is used. This allows you to do arithmetic with environment variable values without having to type all those % signs to get their values. If SET /A is executed from the command line outside of a command script, then it displays the final value of the expression. The assignment operator requires an environment variable name to the left of the assignment operator. Numeric values are decimal numbers, unless prefixed by 0x for hexadecimal numbers, and 0 for octal numbers. So 0x12 is the same as 18 is the same as 022. Please note that the octal notation can be confusing: 08 and 09 are not valid numbers because 8 and 9 are not valid octal digits.
Por otra parte, el sleep.exe
no es el único de los comandos de las “Windows Server 2003 Resource Kit Tools” que van orientados a la creación de ficheros batch. Aunque la mayoría están creados para la línea de comandos y lo normal es que resulten útiles en ficheros batch, hay unos pocos que van en la línea de emular las capacidades de las utilidades de línea de comandos de UNIX:
Qgrep.exe
: Equivalente algrep
de UNIX y más potente que elfind
de WindowsSleep.exe: Batch File Wait
: Equivalente alsleep
de UNIXTail.exe
: Equivalente altail
de UNIXTimeit.exe
: Equivalente altime
integrado en las shell de los UNIX
C:\Program Files\Windows Resource Kits\Tools>timeit.exe notepad.exe Version Number: Windows NT 5.1 (Build 2600) Exit Time: 12:15 pm, Saturday, December 29 2007 Elapsed Time: 0:00:04.406 Process Time: 0:00:00.125 System Calls: 162689 Context Switches: 42825 Page Faults: 1915 Bytes Read: 346645 Bytes Written: 138732 Bytes Other: 465030
De los otros comandos, normalmente de uso muy específico para ciertas tareas, me llama la atención el cdburn
para grabar imágenes ISO desde línea de comandos, como el cdrecord
que se suele usar en Linux:
C:\Program Files\Windows Resource Kits\Tools>cdburn Usage: cdburn <drive> -erase [image [options]] cdburn <drive> image [options] Options: -erase Erases the disk before burning (valid for R/W only) -sao Writes the image out in "session at once", or cue sheet, mode (default is "track at once") -speed Speed of burn, or 'max' for maximum speed -imagehaspostgap Use if your image already contains a 150 sector postgap The [image] must be provided unless the -erase flag is set. If both an image and -erase are provided, the media will be erased prior to burning the image to the disc.
En las Windows XP Service Pack 2 Support Tools también encontramos el “diruse.exe
“, una especie de du
de UNIX:
C:\>diruse c:\windows Size (b) Files Directory 3044783611 14926 SUB-TOTAL: C:\WINDOWS 3044783611 14926 TOTAL: C:\WINDOWS
El pmon.exe
, similar al top
de UNIX:
Memory: 2096492K Avail:1207304K PageFlts: 504 InRam Kernel: 3288K P:94392K Commit: 704468K/ 513192K Limit:4033324K Peak: 717524K Pool N:44052K P:94660K Mem Mem Page Flts Commit Usage Pri Hnd Thd Image CPU CpuTime Usage Diff Faults Diff Charge NonP Page Cnt Cnt Name 219224 -584 1858776 416 File Cache 97 4:32:06 28 0 0 0 0 0 0 0 0 2 Idle Process 0 0:00:32 256 0 13178 0 28 0 0 8 977 82 System 0 0:00:00 392 0 215 0 172 0 6 11 21 3 smss.exe 0 0:00:10 5212 0 9627 0 1868 7 92 13 932 13 csrss.exe 0 0:00:02 13820 0 17590 0 16292 79 146 13 712 31 winlogon.exe 0 0:00:29 3772 0 14877 0 1960 10 45 9 388 16 services.exe 0 0:00:06 8328 0 3536 0 5620 11 90 9 497 26 lsass.exe 0 0:00:01 9896 0 32490 0 6148 36 76 8 229 6 svchost.exe 0 0:00:00 3268 0 947 0 2104 2 39 8 88 5 ati2evxx.exe 0 0:00:00 5276 0 21340 0 3264 5 71 8 222 17 svchost.exe 0 0:00:01 5300 0 23940 0 3372 14 76 8 545 13 svchost.exe 0 0:00:09 21848 0 31536 0 14352 57 184 8 1451 74 svchost.exe
El pstat.exe
, que se parece al ps
de UNIX.
El whoami.exe
, que es como su tocayo UNIX:
C:\>whoami Administrator
¡Ah! Y si necesitamos un uptime
, también hay uno a nuestra disposición en una descarga separada (Uptime.exe Tool Allows You to Estimate Server Availability with Windows NT 4.0 SP4 or Higher):
C:\>uptime \\ORDENADOR has been up for: 0 day(s), 2 hour(s), 26 minute(s), 41 second(s)
De todas formas, donde esté un buen Cygwin…
Actualización 20/8/09:
También podemos hacer fácilmente un sleep
con VBScript y Wscript.Sleep
. Creamos un fichero llamado sleep.vbs
con este contenido:
Wscript.Sleep 5000
y lo ejecutamos así:
cscript sleep.vbs
Si queremos poder elegir el retardo en línea de comandos, la instrucción sería esta:
Wscript.Sleep WScript.Arguments.Item(0)
y el comando lo ejecutamos así:
cscript sleep.vbs 5000
:wq
si no tambien puedes usar el subsistema posix de windows
@makakoloko Te refieres al “Windows Services for UNIX”, ¿verdad?
Lo primero, feliz año nuevo super coco.
Lo segundo, con respecto al uptime, tengo esta macro en el doskey ‘systeminfo $b findstr segundos’. (El $b es para la tubería.)
Es funcional, pero nada más.
Me parece que ya he comentado alguna vez por aquí que me parece criminal que Microsoft venda productos que incluyen características tan limitadas y poco o nada convencionales como el scripting del cmd. Este es el origen de muchos dolores de cabeza de bastantes sysadmins. Lo curioso es que luego intentan arreglarlo con estos packs de utilidades con los que no puedes contar para hacer scripts portables, toda vez que no vienen en una instalación por defecto.
En fin, lo de siempre.
Vi rocks!!!
Muy bueno el artículo, yo he tenido que consultar en varias ocasiones los grupos de discusión sobre windows scripting en google, porque hace poco tuve que programar un script que enviase los logs del ntbackup por correo al terminar la tarea. Y la verdad me siento más cómodo programando scripts en GNU/Linux que Windows, pero con un poco de práctica también se pueden hacer cosas curiosas en Windows.
Saludos, y enhorabuena por el blog
Alex Casanova
@miguel ¡Gracias! ¡Igualmente! ¡Feliz año para ti y para todos los lectores del blog!
¡Totalmente de acuerdo en lo que dices! Respecto al
uptime
, no me acordaba que elsystemnfo
daba esa información, así que ¡muchas gracias por el apunte!@Alex Casanova ¡Me alegro de que te haya gustado! ¡Gracias por la visita!