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 et dmenu
comme lanceur d'application. 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 ne prétends pas que tous les lanceurs d'applications fonctionnent de la même manière car je ne les comprends pas assez bien.
Je connais les façons suivantes de générer des processus à partir du shell:
exec /path/to/Program
remplacer Shell par la commande spécifiée sans créer de nouveau processussh -c /path/to/Program
lancer le processus dépendant de Shell/path/to/Program
lancer le processus dépendant de Shell/path/to/Program 2>&1 &
lancer le processus indépendant de ShellNohup /path/to/Program &
lancer le processus indépendant de Shell et rediriger la sortie vers Nohup.out
Mise à jour 1: je peux illustrer ce que, par exemple dmenu
le reconstruit à partir d'appels répétés à ps -efl
dans des conditions différentes. Il donne naissance à 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 émettez Nohup /path/to/Program &
à partir d'un shell /bin/bash
alors 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 il a PPID 1
alors ce sera le parent du programme. Voici ce que j'ai essayé d'expliquer à l'aide d'un graphique: chromium
a été lancé via dmenu
, firefox
a été lancé à l'aide de 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? Devrait-il par exemple être un Shell ou doit-il être le processus init
c'est-à-dire le processus avec PID 1
?
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 à
$ sh % / chemin/vers/Programme % Ctrl+D(ou vous pouvez taper "sortie") $
où vous démarrez un nouveau processus 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 sh -c "command"
Est surtout utile pour faire des choses délicates, comme encapsuler plusieurs commandes dans un bundle, elles ressemblent donc à une seule commande (sorte de script sans nom à usage unique), ou à construire des commandes compliquées, peut-être à partir de Shell variables. Vous ne l'utiliseriez presque jamais uniquement pour exécuter un seul programme avec des arguments simples.
2>&1
Signifie rediriger l'erreur standard vers la sortie standard. Cela n'a pas grand-chose à voir avec &
; vous l'utilisez plutôt lorsqu'une commande envoie des messages d'erreur à l'écran même si vous dites command > file
et que vous souhaitez capturer les messages d'erreur dans le fichier.Nohup.out
Est un effet secondaire trivial de Nohup
. Le but principal de Nohup command &
Est d'exécuter command
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 pour qu'il ait une meilleure chance de pouvoir continuer à s'exécuter si vous terminez le shell (par exemple, la déconnexion) pendant que la commande est toujours en cours d'exécution.bash(1)
et le Bash Reference Manual sont de bonnes sources d'informations.
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 firefox
par votre programme préféré):
(firefox &)
Une autre consiste à renier le processus:
firefox & disown firefox
Si vous êtes curieux de savoir comment fonctionnent les lanceurs d'applications, dmenu
fournit 1 script binaire et 2 scripts Shell: dmenu
, dmenu_path
et dmenu_run
, respectivement.
dmenu_run
redirige la sortie de dmenu_path
dans dmenu, qui à son tour redirige vers n'importe quel $Shell
la variable est définie sur. S'il est vide, il utilisera /bin/sh
.
#!/bin/sh
dmenu_path | dmenu "$@" | ${Shell:-"/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.
#!/bin/sh
cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
if [ -d "$cachedir" ]; then
cache=$cachedir/dmenu_run
else
cache=$HOME/.dmenu_cache # if no xdg dir, fall back to dotfile in ~
fi
IFS=:
if stest -dqr -n "$cache" $PATH; then
stest -flx $PATH | sort -u | tee "$cache"
else
cat "$cache"
fi
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:
#!/bin/sh
$(dmenu_path | dmenu "$@") &
J'aime beaucoup la réponse de G-Man. Mais je réponds parce que je pense que vous confondez les préoccupations. Comme le souligne Wayne, la meilleure réponse est "tout ce qui obtient les résultats que vous souhaitez".
Dans la gestion des processus Unix, chaque processus a un parent. La seule exception à cela est le processus init
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 par program
, en conservant le parent qui a lancé le Shell.
sh -c /path/to/program
crée en quelque sorte un processus shell enfant qui créera un processus enfant de program
. Cela n'a de valeur que si /path/to/program
est en fait une séquence d'instructions de script, et non un fichier exécutable. (sh /path/to/script.sh
peut être utilisé pour exécuter un script Shell dépourvu d'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 des appels 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 &
(en ignorant 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 Nohup.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 , alors SIGHUP sera envoyé aux enfants. Si ce n'est pas le cas, le processus peut être "orphelin" et hérité par le processus init
.
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 des sous-shells ou des sous-processus, à moins qu'il n'y ait un problème spécifique que vous abordez lié à la gestion des processus.