J'ai du mal à formuler la question avec précision, mais je ferai de mon mieux. J'utilise dwm
comme gestionnaire de fenêtres par défaut etdmenu
comme lanceur d'applications. J'utilise à peine les applications GUI en dehors de mon navigateur. La plupart de mon travail se fait directement à partir de la ligne de commande. De plus, je suis un grand fan du minimalisme concernant les systèmes d'exploitation, les applications, etc. L'un des outils dont je ne me suis jamais débarrassé était un lanceur d'applications. Principalement parce que je ne comprends pas exactement comment fonctionnent les lanceurs d'applications / ce qu'ils font. Même une recherche approfondie sur Internet ne révèle qu'une vague explication. Ce que je veux faire, c'est me débarrasser même de mon lanceur d'applications car en dehors de la création de l'application, je n'ai absolument aucune utilité. Pour ce faire, je voudrais vraiment savoir comment démarrer "correctement" les applications à partir du shell. Ainsi, la signification de "correctement" peut être approximée par "comme le ferait un lanceur d'application".
Je connais les façons suivantes de générer des processus à partir du shell:
exec /path/to/Program
remplacer le shell par la commande spécifiée sans créer de nouveau processussh -c /path/to/Program
lancer un processus dépendant du shell/path/to/Program
lancer un processus dépendant du shell/path/to/Program 2>&1 &
lancer un processus indépendant du shellnohup /path/to/Program &
lancer un processus indépendant du shell et rediriger la sortie versnohup.out
Mise à jour 1: je peux illustrer ce que fait par exemple sa dmenu
reconstruction à partir d'appels répétés ps -efl
dans différentes conditions. Il génère un nouveau shell /bin/bash
et en tant qu'enfant de ce shell, l'application /path/to/Program
. Tant que l'enfant est là, la coquille restera aussi longtemps. (La façon dont il gère cela me dépasse ...) En revanche, si vous sortez nohup /path/to/Program &
d'un shell, /bin/bash
le programme deviendra l'enfant de ce shell MAIS si vous quittez ce shell, le parent du programme sera le processus le plus élevé. Donc, si le premier processus était par exemple /sbin/init verbose
et qu'il a PPID 1
alors, il sera le parent du programme. Voici ce que j'ai essayé d'expliquer à l'aide d'un graphique: a chromium
été lancé via dmenu
, a firefox
été lancé en utilisant exec firefox & exit
:
systemd-+-acpid
|-bash---chromium-+-chrome-sandbox---chromium-+-chrome-sandbox---nacl_helper
| | `-chromium---5*[chromium-+-{Chrome_ChildIOT}]
| | |-{Compositor}]
| | |-{HTMLParserThrea}]
| | |-{OptimizingCompi}]
| | `-3*[{v8:SweeperThrea}]]
| |-chromium
| |-chromium-+-chromium
| | |-{Chrome_ChildIOT}
| | `-{Watchdog}
| |-{AudioThread}
| |-3*[{BrowserBlocking}]
| |-{BrowserWatchdog}
| |-5*[{CachePoolWorker}]
| |-{Chrome_CacheThr}
| |-{Chrome_DBThread}
| |-{Chrome_FileThre}
| |-{Chrome_FileUser}
| |-{Chrome_HistoryT}
| |-{Chrome_IOThread}
| |-{Chrome_ProcessL}
| |-{Chrome_SafeBrow}
| |-{CrShutdownDetec}
| |-{IndexedDB}
| |-{LevelDBEnv}
| |-{NSS SSL ThreadW}
| |-{NetworkChangeNo}
| |-2*[{Proxy resolver}]
| |-{WorkerPool/1201}
| |-{WorkerPool/2059}
| |-{WorkerPool/2579}
| |-{WorkerPool/2590}
| |-{WorkerPool/2592}
| |-{WorkerPool/2608}
| |-{WorkerPool/2973}
| |-{WorkerPool/2974}
| |-{chromium}
| |-{extension_crash}
| |-{gpu-process_cra}
| |-{handle-watcher-}
| |-{inotify_reader}
| |-{ppapi_crash_upl}
| `-{renderer_crash_}
|-2*[dbus-daemon]
|-dbus-launch
|-dhcpcd
|-firefox-+-4*[{Analysis Helper}]
| |-{Cache I/O}
| |-{Cache2 I/O}
| |-{Cert Verify}
| |-3*[{DOM Worker}]
| |-{Gecko_IOThread}
| |-{HTML5 Parser}
| |-{Hang Monitor}
| |-{Image Scaler}
| |-{JS GC Helper}
| |-{JS Watchdog}
| |-{Proxy R~olution}
| |-{Socket Thread}
| |-{Timer}
| |-{URL Classifier}
| |-{gmain}
| |-{localStorage DB}
| |-{mozStorage #1}
| |-{mozStorage #2}
| |-{mozStorage #3}
| |-{mozStorage #4}
| `-{mozStorage #5}
|-gpg-agent
|-login---bash---startx---xinit-+-Xorg.bin-+-xf86-video-inte
| | `-{Xorg.bin}
| `-dwm-+-dwmstatus
| `-xterm---bash-+-bash
| `-pstree
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-udevd
|-wpa_actiond
`-wpa_supplicant
Mise à jour 2: Je suppose que la question peut également se résumer à: Quel devrait être le parent d'un processus? Doit-il par exemple être un shell ou doit-il être le init
processus c'est-à-dire le processus avec PID 1
?
init
- à quoi pourrait être la réponse ... peut-être? cela dépend de comment / si vous prévoyez de lui parler, de ce queinit
vous utilisez et de l'emplacement des canaux de données. En général, ces trucs auront tendance à s'arranger - c'est à ça queinit
sert. Dans tous les cas, généralement lorsque vous démonifiez un processusinit
. Ou si vous voulez contrôler le travail, le shell actuel.dmenu
et voir comment je m'entends avec ce que j'ai appris. Je trouveexec /path/to/Program & exit
ou/bin/bash -c /path/to/Program & exit
être tout à fait utilisable. Mais ils font tous,1
c'est-àinit
- dire le parent de ceProgram
qui me convient tant que cela a du sens et ne viole aucun*nix
principe de base .exec &
, je pense. Habituellement, je fais juste mes affaires depuis le terminal ... peut-être que vous pourriez utiliser la question de Ben Crowell ici . J'ai une réponse là-bas, mais elles sont toutes très bonnes. de toute façon, quand vous fondez un processus et son parent meurt comme:sh -c 'cat & kill $$'
vous l'orphelin, et il finit par être récolté par la suite. c'est le travail d'init - c'est pourquoi ils y tombent tous.systemd--bash--chromium
. Toutes les méthodes que j'essaie mèneront finalement à un arbre de processus de la forme suivantesystemd--chromium
lorsque j'apparaît firefox à partir du shell. Comment l'obus est-il diabolisé ici? Il n'est associé à aucun terminal.Réponses:
Eh bien, vous semblez en avoir une assez bonne compréhension. Pour clarifier une partie de ce que vous avez,
sh -c /path/to/Program
est assez similaire àoù vous démarrez un nouveau processus de shell, fournissez le chemin de commande d'application au nouveau shell, puis laissez le nouveau shell se terminer. J'ai montré le nouveau shell donnant une invite différente à des fins d'illustration; cela n'arriverait probablement pas dans la vraie vie. La construction est surtout utile pour faire des choses délicates, comme encapsuler plusieurs commandes dans un bundle, de sorte qu'elles ressemblent à une seule commande (sorte de script sans nom à usage unique), ou pour construire des commandes compliquées, éventuellement à partir de variables de shell. Vous ne l'utiliseriez presque jamais uniquement pour exécuter un seul programme avec des arguments simples.
sh -c "command"
2>&1
signifie rediriger l'erreur standard vers la sortie standard. Cela n'a pas vraiment grand-chose à voir avec&
; vous l'utilisez plutôt lorsqu'une commande envoie des messages d'erreur à l'écran même si vous dites et que vous souhaitez capturer les messages d'erreur dans le fichier.command > file
nohup.out
est un effet secondaire trivial denohup
. Le but principal de est de s'exécuter de manière asynchrone (communément appelé «en arrière-plan», ou en tant que «processus indépendant du shell», pour utiliser vos mots) et de le configurer afin qu'il ait de meilleures chances de pouvoir continuer à s'exécuter si vous terminer le shell (par exemple, déconnexion) pendant que la commande est toujours en cours d'exécution.nohup command &
command
bash(1)
et le Bash Reference Manual sont de bonnes sources d'information.la source
Il existe plusieurs façons d'exécuter un programme et de le détacher d'un terminal. La première consiste à l'exécuter en arrière-plan d'un sous-shell , comme ceci (remplacez-le
firefox
par votre programme préféré):Une autre consiste à renier le processus:
Si vous êtes curieux de savoir comment les lanceurs d'applications de travail,
dmenu
fournit 1 binaire et 2 scripts shell:dmenu
,dmenu_path
etdmenu_run
, respectivement.dmenu_run
dmenu_path
redirige la sortie de dans dmenu, qui à son tour redirige vers la$SHELL
variable définie. S'il est vide, il utilisera/bin/sh
.dmenu_path
est un peu plus complexe, mais en bref, il fournit une liste de binaires dans votre$PATH
variable d'environnement, et utilise un cache si possible.Il n'est pas nécessaire que les programmes s'exécutent dans des shells. Une autre façon d'écrire
dmenu_run
, sans tuyauterie dans un shell serait:la source
J'aime beaucoup la réponse de G-Man. Mais je réponds parce que je pense que vous confondez les préoccupations. Comme Wayne le fait remarquer, la meilleure réponse est «tout ce qui obtient les résultats souhaités».
Dans la gestion des processus Unix, chaque processus a un parent. La seule exception à cela est le
init
processus qui est démarré par le système d'exploitation au démarrage. Il est normal qu'un processus parent emporte tous ses processus enfants avec lui lorsqu'il meurt. Cela se fait en envoyant le signal SIGHUP à tous les processus enfants; la gestion par défaut de SIGHUP met fin au processus.La génération de shell des processus utilisateur n'est pas différente de celle que vous avez codée pour les appels fork (2) / exec (3) dans la langue de votre choix. Le shell est votre parent, et si le shell se termine (par exemple, vous vous déconnectez), le ou les processus enfants qu'il génère vont de pair. Les nuances que vous décrivez ne sont que des moyens de modifier ce comportement.
exec /path/to/program
c'est comme appeler exec (3) . Oui, il remplacera votre shell parprogram
, en gardant le parent qui a lancé le shell.sh -c /path/to/program
crée inutilement un processus shell enfant qui créera un processus enfant deprogram
. Il n'est utile que s'il/path/to/program
s'agit en fait d'une séquence d'instructions de script et non d'un fichier exécutable. (sh /path/to/script.sh
peut être utilisé pour exécuter un script shell sans autorisations d'exécution dans un shell inférieur)/path/to/program
crée un processus de "premier plan", ce qui signifie que le shell attend la fin du processus avant de prendre toute autre action. Dans le contexte d'un appel système, c'est comme fork (2) / exec (3) / waitpid (2) . Notez que l'enfant hérite de stdin / stdout / stderr du parent./path/to/program &
(ignorer la redirection) crée un "processus d'arrière-plan". Le processus est toujours un enfant du shell, mais le parent n'attend pas qu'il se termine.nohup /path/to/program
invoque nohup (1) pour empêcher l'envoi de SIGHUP àprogram
si le terminal de contrôle est fermé. Que ce soit au premier plan ou en arrière-plan est un choix (bien que le plus souvent le processus soit en arrière-plan). Notez que cenohup.out
n'est que la sortie si vous ne redirigez pas autrement stdout.Lorsque vous mettez un processus en arrière-plan, si le processus parent meurt, l'une des deux choses se produit. Si le parent est un terminal de contrôle , SIGHUP sera envoyé aux enfants. Si ce n'est pas le cas, le processus peut être "orphelin" et hérité par le
init
processus.Lorsque vous redirigez les entrées / sorties / erreurs, vous connectez simplement les descripteurs de fichiers de chaque processus à des fichiers différents de ceux dont il hérite de son parent. Rien de tout cela n'affecte la propriété du processus ou la profondeur de l'arborescence (mais il est toujours judicieux de rediriger les 3 loin d'un terminal pour les processus d'arrière-plan).
Cela dit, je ne pense pas que vous devriez vous préoccuper de la création de processus par le shell ou les sous-shells ou les sous-processus, à moins qu'il n'y ait un problème spécifique que vous abordez lié à la gestion des processus.
la source
sh -c /path/to/program
pas le programme en tant que script shell s'il manque les bits exécutables, lesh /path/to/program
fera.sh -c /path/to/program
ouvrira simplement un shell et s'exécutera/path/to/program
comme une commande dans ce shell, qui échouera s'il n'est pas exécutable.sh -c /path/to/program
lit les commandes depuis/path/to/program
comme entrée dans le shell. Il ne nécessite pas que le fichier dispose d'une autorisation d'exécution, mais il doit s'agir d'un script shellsh /path/to/program
fait ça. Je viens de l'essayer moi-même :,echo echo hello world >abc.sh
puissh ./abc.sh
imprimehello world
, tandis quesh -c ./abc.sh
ditsh: ./abc.sh: Permission denied
(ce qui est le même que si vous exécutiez./abc.sh
directement dans le shell actuel.) Ai-je raté quelque chose? (Ou peut-être que je ne me suis pas bien exprimé dans le commentaire précédent ...)sh -c _something_
revient à taper simplement_something_
à l'invite de commande, à l'exception du frai du shell inférieur. Vous avez donc raison qu'il échouera s'il manque le bit d'exécution (sous forme de fichier). D'un autre côté, vous pouvez fournir une série de commandes shell commesh -c "echo hello world"
et cela fonctionnera très bien. Donc, cela ne nécessite pas que ce que vous tapez ait le bit d'exécution (ou même un fichier), seulement que l'interpréteur de shell puisse faire quelque chose avec.