Ejecutar múltiples procesos en segundo plano concurrentes y luego esperar a que todos terminen en Windows

12

¿Alguien sabe si hay un script cmd que lo haga y / o una herramienta de línea de comando lista para el trabajo?

Sergio
fuente
¡Hacerlo puede dañar sus datos!
Santosh Kumar
8
@Santosh: ¿qué quieres decir con "puede dañar tus datos"? En mi caso específico, las tareas en segundo plano procesarían sus propios conjuntos de datos independientes. Sin riesgos de modificaciones concurrentes.
Sergio
1
Desde el lado de la API Win32, creo que WaitForMultipleObjects con bWaitAll = TRUE haría el trabajo. No sería difícil escribir un programa que simplemente bifurca los programas dados en algún archivo de entrada, si no hay respuestas satisfactorias.
Grawity
1
@grawity: sí, planeo hacer eso si no aparece nada (y publicar el código aquí), pero veamos si puedo evitar reinventar la rueda :)
Sergio
Reinventar la rueda es algo bueno si las ruedas existentes actualmente son cuadradas ...
Grawity

Respuestas:

8

Cree los tres archivos por lotes a continuación. Main.bat lanza 1.bat y 2.bat

1.bat y 2.bat escriben archivos temporales para los cuales main.bat comprueba. Mientras 1.bat y 2.bat están funcionando, main.bat informa que el procesamiento todavía está ocurriendo. Cuando presionas enter en la ventana abierta de 1.bat o 2.bat, el archivo temporal se elimina y el programa se cierra. Esto simula el proceso de detención para ese archivo .bat. Si hace esto para 1 y 2.bat, main.bat le informa que el procesamiento se ha completado para estos procesos. Puede hacer que 1.bat y 2.bat hagan lo que quiera, siempre que borre el archivo temporal cuando haya terminado. En este punto, main.bat puede hacer lo que usted quiera que haga también.

1.bat

echo %time% > 1.tmp
pause
del 1.tmp
exit 

2.bat

echo %time% > 2.tmp
pause
del 2.tmp
exit

main.bat

@echo off
start "1" 1.bat
start "2" 2.bat
    @ping -n 1 127.0.0.1 > nul
:loop
@echo Processing......
if not exist *.tmp goto :next
    @ping -n 5 127.0.0.1 > nul
goto loop
:next
@echo Done Processing!
RobW
fuente
Habiendo hecho esto antes, puedo decirles que este enfoque no es tan difícil como parece. Además, es fácil de mantener: expandir y agregar lógica, y es fácil capacitar a alguien más para mantenerlo. Por lo general, estas cosas cobran vida por sí mismas ...
RobW
Estoy contento con esta solución.
user1068446
3

Suficientemente simple, siempre que los procesos no necesiten entrada o salida estándar. Desde la línea de comando o en un archivo por lotes:

process1 | process2 | process3 | process4

Esto ejecutará los cuatro procesos simultáneamente, y no volverá hasta que todos hayan salido. (Posible excepción: si un proceso cierra explícitamente la salida estándar, podría tratarse como si hubiera salido. Pero eso es inusual, muy pocos procesos lo hacen).

No estoy seguro de cuántos procesos puede iniciar simultáneamente de esta manera. He probado hasta diez.

Harry Johnston
fuente
Uhm, lo que obtengo es que todos los procesos se inician de una vez, pero el proceso3 se mantiene esperando hasta que el proceso4 se haya completado, el proceso2 se mantiene esperando hasta que el proceso3 se complete, y así sucesivamente. Por cierto, esto es del símbolo del sistema clásico de Windows.
Sergio
@ Sergio: ¿Qué quieres decir con "seguí esperando"?
Harry Johnston
1

La única forma de hacer esto es iniciar archivos por lotes separados (ver start /?) que ejecutan la tarea individual y escribir un archivo de texto al finalizar. Luego, verifica periódicamente si se han creado los archivos de texto.

Tamara Wijsman
fuente
0

Puede consultar el cmdlet Powershell Start-Job. Debería permitirte hacer esto. Más aquí Powershell es el shell de elección de Microsoft. Es mucho más potente que los scripts de cmd y vale la pena invertir su tiempo.

uSlackr
fuente
¿Esto no espera a que todos terminen?
Tamara Wijsman
Ciertamente puede, dependiendo de cómo lo escriba. Puede sondear los trabajos iniciados para ver si se han completado y salir de su script una vez que lo hayan hecho. El código en esa página procesa una lista completa de trabajos, tres a la vez y espera a que salgan.
uSlackr
Uhm, nunca antes había hecho nada con Powershell. Traté de cambiar el ejemplo para ejecutar procesos arbitrarios y esperar a que se completaran y después de aproximadamente 30 minutos y 100 búsquedas en M $ technet me di por vencido. Lo siento si hiero los sentimientos de alguien, pero Powershell es una mierda. Es más fácil hacer esto en C (lo que creo es revelador ...) Gracias de todos modos, apuesto a que a alguien aún le resultará útil.
Sergio
Si hay algo que Powershell no es es basura y no herirás mis sentimientos si no lo usas. Sin embargo, no lo aprenderá en 30 minutos de búsqueda.
uSlackr
1
PowerShell no es una mierda, es solo un lenguaje de programación completo que uno tiene que aprender, en lugar de una sintaxis tradicional tipo sh. Recuerdo que me sentí exactamente igual sobre Perl, Python, Tcl, C # y cualquier otro idioma que intenté aprender "para el lulz" sin ningún uso real todavía. (Cuando realmente los necesitaba , sin embargo, fue bastante fácil)
Grawity
0

O puede usar esto: http://www.out-web.net/?p=167

Lo hice, funciona, sin embargo, a veces sucede que el PID del proceso terminado es reutilizado inmediatamente por otro proceso de Windows que acaba de comenzar, y hace que la detección del final de su proceso sea peligrosa / errónea.

OlivierR
fuente
2
Resuma lo que dice ese enlace. Si la página se cae, esta respuesta no será útil.
Kevin Panko
Demasiado tarde es parece.
Robert Massa
0

También estaba buscando una tarea similar. El objetivo era ejecutar múltiples comandos en paralelo y extraer la salida (stdout y error) de todos los procesos paralelos. Luego espere a que finalicen todos los procesos paralelos y ejecute otro comando. El siguiente es un código de muestra para el archivo BAT, se puede ejecutar en CMD:

( start "" /B cmd /c ping localhost -n 6 ^>nul timeout /t 5 /nobreak start "" /B /D "C:\users\username\Desktop" cmd /c dir ^> dr.txt ^2^>^&^1 start "" /B cmd /c ping localhost -n 11 ^>nul timeout /t 10 /nobreak ) | pause Echo waited timeout /t 12 /nobreak

Todas las declaraciones dentro ()se ejecutan primero, espere a que se completen, luego se ejecutan las últimas dos líneas. Todos los comandos que comienzan startse ejecutan simultáneamente.

Estos enlaces son útiles: https://stackoverflow.com/a/43762349/9689416 y https://ss64.com/nt/start.html

Vivek
fuente