Ejecutar un proceso de fondo bash en Windows 10 sin un terminal abierto

13

Usualmente uso el subsistema Linux cuando estoy programando cualquier cosa en Windows 10, por lo que todas mis rutas son relativas ~. Tengo un script de Python que se ejecuta para siempre en segundo plano hasta que elimine el proceso. ¿Cómo haría eso en Windows 10 bash sin un terminal abierto?

Cosas que he probado:

  • bash -c "python3 script.py de Run.
  • nohup python3 -u script.py luego cerrando la terminal.
  • setsid python3 script.py luego cerrando la terminal.

Ninguno de estos funcionó. ¿Hay alguna forma de hacer esto? Alternativamente, ¿hay alguna manera de alterar las rutas para que funcionen si ejecuto el script desde W10 AND bash sin tener que cambiarlas cada vez?

Ceniza
fuente

Respuestas:

7

Una adición reciente a WSL permite iniciar comandos wsl directamente desde el menú 'Ejecutar' o Inicio. Puede agregar un ampersand al comando (comportamiento de shell normal), lo que da como resultado un bashterminal momentáneo que desaparece inmediatamente pero el comando continúa.

Ejemplos, dentro de Inicio »Ejecutar :

wsl sleep 20 &
wsl python -c 'import time; time.sleep(20);' &

Si ingresa al Administrador de tareas de Windows, mostrará un comando Sleepo un Python2comando ejecutándose durante 20 segundos, luego se borrará automáticamente.

Una cosa que he encontrado es que las variables de entorno no están disponibles. Por ejemplo, DISPLAYsi se establece en el método normal de Windows, no se pasa a WSL. Para esto, debe haber una forma de pasar estas variables. Incluso si el comando no admite la configuración de la variable necesaria a través de un argumento de línea de comando, es posible hacerlo usando él bashmismo:

# direct, command-dependent
wsl emacs --display=:0 &

# indirect, more flexible
wsl bash -c "DISPLAY=:0 emacs" &

NB: actualmente estoy ejecutando win10_64, versión 1709 (compilación del SO 16299.64).

r2evans
fuente
13

Actualizar

Microsoft ha abordado esto. Ahora se permite que los procesos en segundo plano / daemon continúen ejecutándose incluso después de que bash.exese cierre (u otro proceso de iniciador WSL). Se requiere una compilación reciente de Win10 (primavera de 2018 para lanzamientos públicos, compilación 17046 o superior).

Lo siguiente se conserva para la posteridad.


Tristemente / absurdamente, no hay forma de hacer esto. Microsoft, en su sabiduría infinita, ha decidido que WSL (Windows Subsystem for Linux) solo se ejecutará mientras tenga un bash.exeproceso abierto. Cierre la última (o posiblemente cierre la última ventana ; no estoy seguro de si tolerará que se ejecute sin cabeza) y WSL se cierra, matando todos sus procesos.

La justificación de esto fue "conservar los recursos", lo cual es absurdo en varios niveles diferentes, pero sobre todo porque, ¡maldita sea, mi computadora tiene esos recursos y están ahí para ser utilizados! Si quiero que se ejecute un proceso, debería ejecutarse; si no quiero que se ejecute, puedo matarlo. Para algo explícitamente pensado como una herramienta de desarrollo, a veces parece que WSL solo se puede usar como un juguete y no se puede confiar en sus usuarios para saber lo que están haciendo.

De todos modos, si quiere que esto se solucione, vote por Considere la posibilidad de habilitar trabajos cron, demonios y tareas en segundo plano en la página UserVoice . Actualmente es la segunda solicitud más votada y está "en la cartera".

CBHacking
fuente
"sobre todo porque, maldita sea, mi computadora tiene esos recursos y están ahí para ser utilizados" ¡muy bien dicho! realmente aturde la mente ...
ataque aéreo
Tengo la compilación 17134 y no puedo tener un trabajo en segundo plano sin una ventana bash.
John Pick
@JohnPick No se iniciarán automáticamente después de un reinicio, pero deberían seguir ejecutándose cuando la ventana esté cerrada (siempre y cuando no estén conectados a ella, por supuesto).
CBHacking
@CBHacking Para ser más específico, si inicio un servidor Node.js en segundo plano, es tanto un trabajo ( jobs) como un proceso ( ps aux). Puedo usar fgpara traerlo al primer plano. Pero, después de cerrar la última ventana de bash y abrir una nueva ventana de bash, el trabajo se ha ido, el proceso aún se está ejecutando y no puedo mover el proceso al primer plano. Lo siento si mi terminología está apagada.
John Pick el
@JohnPick Ah, ese es un tema completamente diferente: esta pregunta es sobre procesos, no sobre la gestión de trabajos de shell, y debería haberse preguntado en otro lugar, pero la respuesta es bastante simple. Lo daré aquí: inicie el proceso en tmuxo screenpara apoyar volver a conectar a un terminal diferente. Las máquinas Linux (y otras * nix) que se ejecutan de forma nativa tienen la misma limitación.
CBHacking
2

Sí, es "imposible" en este momento.

Pero es posible que "aparezca" como un proceso en segundo plano con algunos trucos. Quería esta funcionalidad bastante mal, así que después de un par de horas se me ocurrió una solución de mierda pero funcional.

El punto principal es crear un shell invisible al que inicie WSL Bash con VBScript. Luego puede hacer que ese script se ejecute al inicio. La programación adecuada de tareas no funcionó por alguna extraña razón.

Del lado de Linux para habilitar demonios, puede tener su propio sistema de inicio rudimentario que abusa de .bashrc, por ejemplo.

El proceso se detalla aquí en este documento que escribí https://emil.fi/bashwin . No implementé el monitoreo de tareas, pero debería ser bastante fácil de extender.

Emil
fuente
2

¿Has probado esta solución?

Utiliza un ayudante de WSH para iniciar cualquier aplicación oculta.

Luego, puede crear una nueva tarea en Tak Scheduler para iniciar el comando cuando inicie sesión. Algo comowscript <path to runHidden.vbs> bash.exe -c "python script.py"

Magnus
fuente
2

Me llevó una eternidad, pero encontré una forma estúpidamente complicada de hacerlo (a partir de un archivo por lotes):

start bash -c "DISPLAY=:0 [command] & (sleep 0.5 && kill -n 9 $$)"

Aquí hay un desglose de lo que hace y por qué:

  • `start`: para hacer que la ventana del archivo por lotes desaparezca
  • `bash -c`: le permite ejecutar un comando bash
  • `DISPLAY =: 0`: configura su servidor X
  • `[comando]`: su comando / comandos (`[comando && [comando]`)
  • `` Y: para hacer la siguiente ejecución de comandos después de que se inicia y no cuando se realiza
  • `sleep 0.5`: para asegurarse de que el proceso ha comenzado
  • `&&`: para hacer que el siguiente comando se ejecute después de haberlo hecho y no cuando se inicia
  • `kill -n 9 $$`: para matar el shell bash para que sea solo la aplicación gráfica

Nota: lo DISPLAY=:0establece en el servidor x en :0. Para cambiarlo a (por ejemplo) :1, hacer, DISPLAY=:1etc.

Nota: startsolo se requiere si es de un script por lotes. Si es de la terminal, no necesitas esto

Nota: sleepdebe configurarse de manera diferente para cada aplicación. Es posible que incluso deba omitirlo.

Electroboss
fuente
0

No sé qué tan bien Windows Service Manager (SrvMan) de http://tools.sysprogs.org/srvman/ funcionaría para usted, pero me ha funcionado para otros programas. De hecho, intenté ejecutar el "bash.exe" como un servicio para ver si funcionaba, y supongo que tengo que pensar un poco más para que LAMP funcione realmente en segundo plano.

Charles McDonald
fuente
1
¿Cómo aborda esto la cuestión de cómo ejecutar un script Python en segundo plano?
Scott