Lo hice y lo entendí

El blog de Vicente Navarro
29 dic

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 al grep de UNIX y más potente que el find de Windows
  • Sleep.exe: Batch File Wait: Equivalente al sleep de UNIX
  • Tail.exe: Equivalente al tail de UNIX
  • Timeit.exe: Equivalente al time 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

Entradas relacionadas

5 Comentarios a “sleep en scripts de Windows. Operaciones aritméticas en CMD. Comandos para scripting del ResKit.”

  • makakoloko dice:

    si no tambien puedes usar el subsistema posix de windows

  • @makakoloko Te refieres al “Windows Services for UNIX”, ¿verdad?

  • miguel dice:

    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 el systemnfo daba esa información, así que ¡muchas gracias por el apunte!

    @Alex Casanova ¡Me alegro de que te haya gustado! ¡Gracias por la visita!

Tema LHYLE09, creado por Vicente Navarro