Redirigir la canalización a una variable en el archivo por lotes de Windows

9

Quiero detener e iniciar un servicio de Windows desde una PC remota utilizando la línea de comandos de Windows, en un archivo por lotes.

sc \\192.168.1.1 stop <ServiceName>

rem sc \\192.168.1.1 query <ServiceName> | findstr STATUS | SET VAR=

Sin embargo, quiero esperar hasta que se asegure que el estado del servicio se detendrá o se iniciará. Entonces estaba planeando hacer un bucle y verificar el estado continuamente hasta que el estado se DETENGA.

Creo que la solicitud repetida al servidor puede ser intensiva en el procesador, pero no hay que esperar la línea de comando, excepto por algunos trucos en el tiempo de verificación. Pero mi pregunta principal es ¿cómo obtengo el estado del servicio de Windows para poder verificar con una declaración IF si está bien continuar con el siguiente comando?

Nassign
fuente

Respuestas:

9

Para establecer una variable en la salida de un comando, use for /f:

for /f "tokens=*" %%a in ('command') do set _CmdResult=%%a

El problema es utilizar un tubo en el comando que necesita para escapar de ella con el carácter de escape de línea de comandos: ^Por lo tanto: ^|.

for /f "tokens=*" %%a in ('sc \\192.168.1.1 query <ServiceName> ^| findstr STATUS') do set _CmdResult=%%a

Ahora, no estoy seguro de qué versión de Windows está ejecutando, pero mis intentos de una scconsulta en Windows 7 dan el siguiente resultado:

>sc query SamSs
SERVICE_NAME: SamSs
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

Esto significa findstr STATEque sería necesario, lo que da el resultado:

>sc query SamSs | findstr STATE
        STATE              : 4  RUNNING

Ahora, en el ejemplo anterior, tokens=*significa que cada ficha se establece en la variable %%a, donde las fichas están separadas por espacios. En este caso, puede usar el tercer token ( 4) o el cuarto token ( RUNNING). Por cierto, con las pruebas, 1corresponde a STOPPEDmí.

Para facilitar las cosas, usaré la cadena RUNNINGen este ejemplo. Entonces queremos la cuarta ficha.

for /f "tokens=4" %%a in ('sc \\192.168.1.1 query <ServiceName> ^| findstr STATE') do set _CmdResult=%%a

Por supuesto, dependiendo de cuáles sean sus sc queryresultados, los suyos pueden ser ligeramente diferentes, así que siga cómo llegué allí y modifique según sea necesario. O publique en un comentario el resultado de su sc queryy lo modificaré según sea necesario.

Para verificar el valor, puede usar:

if %_CmdResult%==STOPPED (
    REM do something here
)

En su caso, el ciclo sería algo como esto.

:loop
for /f "tokens=*" %%a in ('sc \\192.168.1.1 query <ServiceName> ^| findstr STATUS') do set _CmdResult=%%a
if %_CmdResult%==STOPPED (
    sc \\192.168.1.1 start <ServiceName>
    goto endloop
)
timeout /t 5
goto loop
:endloop

Tenga en cuenta que timeoutes una utilidad que solo se incluye en Windows Vista y versiones posteriores. Windows XP puede usar algo como ping 1.1.1.1 -n 1 -w 5000 > nul .

Mover
fuente
Gracias Bob, fue muy detallado. Pero supongo que lo que faltaba en mi código fue la tubería que se escapó con el carácter de intercalación. Pero esto sería útil para futuras referencias. :)
Nassign
1
Gracias por ^|estar | was unexpected at this time.sin él.
Nae
muchas gracias por el ^ | !!
Smock
1

Un ejemplo más avanzado con mayor nivel de complejidad.

(pero también mayor usabilidad)

  • usando varias aplicaciones comunes ( cURL, GREP, SED) usted puede descargar un Win32 pre-construir versiones de esos o utilizar cygwin archivos exe 's en Windows- tanto funciona perfectamente bien (para cygwin, mejor sólo hay que poner c:\cygwin\bin\ubicación de la carpeta en su sistema PATHvariable para un acceso más fácil )
  • Procesamiento de PIPE (STDOUT y STDERR se procesan a través de).
  • escapado símbolos ( |, >, &) - las mejores prácticas / requerido en Windows 7 +.
  • sin bucles , sin goto
  • trabajando con datos numéricos ( curlencabezado de respuesta Content-Length)
  • Y ... ¡ NO HAY ARCHIVOS TEMPORALES!


@echo off

setlocal enableextensions
  for /f "tokens=*" %%a in ('curl --head --ipv4 --sslv3 --silent --location-trusted --url "https://storage.googleapis.com/chromium-browser-continuous/Win_x64/362418/mini_installer.exe" 2^>^&1 ^| grep "Content-Length" 2^>^&1 ^| sed "s/\r\n$//g" 2^>^&1 ^| sed "s/content-length\:\ //gi" 2^>^&1') do ( set /a num=%%a )

  set /a num=%num% / 1024 / 1024

  echo it is %num%MB
endlocal

saldrá it is 41MB

(el encabezado original es Content-Length: 43597312)


lo tomé de aquí: - CMD / Bash Script Ninja - Manipulación del número de encabezado de respuesta cURL


fuente
0

Es posible que desee consultar PsTools de Microsoft (Sysinternals). Existe una herramienta llamada PsService donde puede verificar de forma remota los servicios a través del parámetro\\computer

JohannesM
fuente
-2

es solo un ejemplo para saber cómo puede "establecer aaa" fuera "aaa = 1 toto" la primera une () fuera "aaa = 1 toto" pero la línea solo después de decir "Variable de entorno aaa no definida"

echo toto tata titi|awk.exe -F"tata" "{print NR,$1}"|(set /p yyy=&set yyy)
set yyy
Risoos
fuente
1
No entiendo cómo esto responde la pregunta. Parece que estás respondiendo una pregunta diferente.
Chenmunka
lo siento, no soy bueno en inglés loll ... cuando lo hago: echo toto tata titi | awk.exe -F "tata" "{print NR, $ 1}" | (set / p aaa = & set aaa) el set aaa en al final de la línea de impresión: yyy = 1 toto el conjunto yyy en la segunda línea de impresión: Variable de entorno yyy no está definido cómo puede cambiar la primera línea del código para ese conjunto yyy de la segunda línea de impresión: yyy = 1 toto
Risoos