Exécution d'un processus d'arrière-plan bash sur Windows 10 sans terminal ouvert

13

J'utilise généralement le sous-système Linux lorsque je programme quoi que ce soit sur Windows 10, donc tous mes chemins sont relatifs à ~. J'ai un script python qui s'exécute pour toujours en arrière-plan jusqu'à ce que je tue le processus. Comment pourrais-je faire cela sur Windows 10 bash sans terminal ouvert?

Ce que j'ai essayé:

  • bash -c "python3 script.py de Run.
  • nohup python3 -u script.py puis fermeture du terminal.
  • setsid python3 script.py puis fermeture du terminal.

Rien de tout cela n'a fonctionné. Y a-t-il un moyen de faire cela? Sinon, existe-t-il un moyen de modifier les chemins afin qu'ils fonctionnent si j'exécute le script à partir de W10 ET bash sans avoir à les changer à chaque fois?

Cendre
la source

Réponses:

7

Un ajout récent à WSL permet de démarrer les commandes wsl directement à partir du menu «Exécuter» ou Démarrer. Vous pouvez ajouter une esperluette à la commande (comportement normal du shell), ce qui entraîne un bashterminal momentané qui disparaît immédiatement mais la commande continue.

Exemples, dans Démarrer »Exécuter :

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

Si vous allez dans le Gestionnaire des tâches de Windows, il affichera une commande Sleepou Python2s'exécutant pendant 20 secondes, puis s'auto-effacera.

Une chose que j'ai trouvée est que les variables d'environnement ne sont pas disponibles. Par exemple, DISPLAYs'il est défini dans la méthode normale de Windows, il n'est pas transmis à WSL. Pour cela, il doit exister un moyen de transmettre ces variables. Même si la commande ne prend pas en charge la définition de la variable requise via un argument de ligne de commande, il est possible de le faire en utilisant bashelle-même:

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

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

NB: J'utilise actuellement win10_64, version 1709 (OS Build 16299.64).

r2evans
la source
13

Mise à jour

Microsoft a résolu ce problème. Les processus d'arrière-plan / démon peuvent désormais continuer à s'exécuter même après la bash.exefermeture (ou tout autre processus de lancement WSL). Une version récente de Win10 (printemps 2018 pour les versions publiques, version 17046 ou supérieure) est requise.

Ce qui suit est conservé pour la postérité.


Malheureusement / absurdement, il n'y a aucun moyen de le faire. Microsoft, dans leur infinie sagesse, a décidé que WSL (Windows Subsystem for Linux) ne fonctionnerait que si un bash.exeprocessus était ouvert. Fermez la dernière (ou peut-être même fermez la dernière fenêtre ; je ne sais pas si elle tolérera d'être exécutée sans tête) et WSL s'arrête, tuant tous ses processus.

La justification en était "de conserver les ressources", ce qui est absurde à plusieurs niveaux mais surtout parce que, bon sang, mon ordinateur a ces ressources et elles sont là pour être utilisées! Si je veux qu'un processus s'exécute, il doit s'exécuter; si je ne veux pas qu'il fonctionne, je peux le tuer. Pour quelque chose explicitement conçu comme un outil de développement, il semble parfois que WSL ne soit utilisable qu'en tant que jouet et que ses utilisateurs ne peuvent pas faire confiance pour savoir ce qu'ils font.

Quoi qu'il en soit, si vous souhaitez résoudre ce problème, votez pour Envisagez d'activer les tâches cron, les démons et les tâches d'arrière-plan sur la page UserVoice . C'est actuellement la deuxième demande la plus votée, et elle est "en retard".

CBHacking
la source
"notamment parce que, bon sang, mon ordinateur a ces ressources et elles sont là pour être utilisées" très bien! ça épate vraiment l'esprit ...
frappe aérienne
J'ai la build 17134 et je ne peux pas avoir de job d'arrière-plan sans fenêtre bash.
John Pick
@JohnPick Ils ne se lanceront pas automatiquement après un redémarrage, mais ils devraient continuer à fonctionner lorsque la fenêtre est fermée (tant qu'ils n'y sont pas attachés, bien sûr).
CBHacking
@CBHacking Pour être plus précis, si je démarre un serveur Node.js en arrière-plan, c'est à la fois un travail ( jobs) et un processus ( ps aux). Je peux utiliser fgpour le mettre au premier plan. Mais, après avoir fermé la dernière fenêtre bash et ouvert une nouvelle fenêtre bash, le travail a disparu, le processus est toujours en cours et je ne peux pas déplacer le processus au premier plan. Désolé si ma terminologie est désactivée.
John Pick
@JohnPick Ah, c'est un problème complètement différent - cette question concerne les processus, pas la gestion des tâches shell - et aurait dû être posée ailleurs, mais la réponse est assez simple, je vais la donner ici: lancer le processus sous tmuxou screenpour soutenir se rattacher à un autre terminal. Les machines Linux (et autres * nix) fonctionnant nativement ont la même limitation.
CBHacking
2

Ouais, c'est "impossible" pour le moment.

Mais il est possible de le faire "apparaître" comme un processus d'arrière-plan avec quelques ruses. Je voulais moi-même assez mal cette fonctionnalité, donc après quelques heures, j'ai trouvé une solution merdique mais fonctionnelle.

Le point principal est de créer un shell invisible sur lequel vous lancez WSL Bash avec VBScript. Vous pouvez ensuite exécuter ce script au démarrage. Une bonne planification des tâches n'a pas fonctionné pour une raison étrange.

Côté Linux, pour activer les démons, vous pouvez avoir votre propre système de démarrage rudimentaire qui abuse de .bashrc par exemple.

Le processus est détaillé ici dans ce document que j'ai écrit https://emil.fi/bashwin . Je n'ai pas implémenté la surveillance des tâches mais cela devrait être assez facile à étendre.

Emil
la source
2

Avez-vous essayé cette solution?

Il utilise un assistant WSH pour lancer toute application masquée.

Ensuite, vous pouvez simplement créer une nouvelle tâche dans Tak Scheduler pour lancer la commande lorsque vous vous connectez. Quelque chose commewscript <path to runHidden.vbs> bash.exe -c "python script.py"

Magnus
la source
2

Cela m'a pris une éternité mais j'ai trouvé une façon stupidement compliquée de le faire (à partir d'un fichier batch):

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

Voici une ventilation de ce qu'il fait et pourquoi:

  • `start`: pour faire disparaître la fenêtre du fichier batch
  • `bash -c`: vous permet d'exécuter une commande bash
  • `DISPLAY =: 0`: définit votre serveur X
  • `[commande]`: votre commande / commandes (`[commande && [commande]`)
  • `&`: pour exécuter la prochaine commande après son démarrage et non lorsqu'elle est terminée
  • `sleep 0.5`: pour vous assurer que le processus a commencé
  • `&&`: pour exécuter la prochaine commande une fois qu'elle est terminée et non lorsqu'elle démarre
  • `kill -n 9 $$`: pour tuer le shell bash afin que ce ne soit que l'application graphique

Remarque: le DISPLAY=:0définit sur le x-server à :0. Pour le changer (par exemple) :1, faites DISPLAY=:1etc.

Remarque: startn'est requis que s'il provient d'un script batch. Si c'est du terminal, vous n'en avez pas besoin

Remarque: sleepdoit être défini différemment pour chaque application. Vous devrez peut-être même l'omettre.

Electroboss
la source
0

Je ne sais pas si Windows Service Manager (SrvMan) de http://tools.sysprogs.org/srvman/ fonctionnerait bien pour vous, mais cela a fonctionné pour moi pour d'autres programmes. En fait, j'ai essayé d'exécuter le "bash.exe" en tant que service pour voir si cela fonctionnerait, et je suppose que je dois bricoler un peu plus pour que LAMP fonctionne réellement en arrière-plan.

Charles McDonald
la source
1
Comment cela répond-il à la question de savoir comment exécuter un script Python en arrière-plan?
Scott