Es fällt mir schwer, die Frage genau zu formulieren, aber ich werde mein Bestes geben. Ich benutze dwm
als Standard Windows Manager unddmenu
als mein Anwendungsstarter. Abgesehen von meinem Browser verwende ich kaum GUI-Anwendungen. Die meiste Arbeit erledige ich direkt über die Kommandozeile. Außerdem bin ich ein großer Fan von Minimalismus in Bezug auf Betriebssysteme, Anwendungen usw. Eines der Tools, das ich nie losgeworden bin, war ein Anwendungsstarter. Hauptsächlich, weil ich nicht genau verstehe, wie Anwendungsstarter funktionieren / was sie tun. Sogar umfangreiche Internetrecherchen zeigen nur vage Erklärungen. Was ich tun möchte, ist, sogar meinen Anwendungsstarter loszuwerden, da ich, abgesehen vom eigentlichen Spawnen der Anwendung, absolut keinen Nutzen dafür habe. Dazu möchte ich wirklich wissen, wie man Anwendungen von der Shell aus "richtig" startet. Wobei die Bedeutung von "richtig" durch "wie ein Anwendungsstarter" angenähert werden kann.
Ich kenne die folgenden Möglichkeiten, um Prozesse aus der Shell zu erzeugen:
exec /path/to/Program
Ersetzen Sie die Shell durch den angegebenen Befehl, ohne einen neuen Prozess zu erstellensh -c /path/to/Program
Starten Sie den Shell-abhängigen Prozess/path/to/Program
Starten Sie den Shell-abhängigen Prozess/path/to/Program 2>&1 &
Starten Sie den Shell-unabhängigen Prozessnohup /path/to/Program &
Starten Sie den Shell-unabhängigen Prozess und leiten Sie die Ausgabe an umnohup.out
Update 1: Ich kann veranschaulichen, was z. B. dmenu
die Rekonstruktion von wiederholten Aufrufen ps -efl
unter verschiedenen Bedingungen bedeutet. Es wird eine neue Shell erzeugt /bin/bash
und als Kind dieser Shell die Anwendung /path/to/Program
. Solange das Kind in der Nähe ist, ist die Muschel in der Nähe. (Wie es das schafft, ist mir ein Rätsel ...) Wenn Sie dagegen nohup /path/to/Program &
von einer Shell ausgehen, /bin/bash
wird das Programm das untergeordnete Element dieser Shell, ABER wenn Sie diese Shell beenden, wird das übergeordnete Element des Programms der oberste Prozess. Wenn also der erste Prozess zB war /sbin/init verbose
und es PPID 1
dann hat, wird es der Elternteil des Programms sein. Hier ist, was ich anhand eines Diagramms zu erklären versuchte: chromium
Wurde gestartet über dmenu
, firefox
wurde gestartet mit 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
Update 2: Ich denke, die Frage kann auch auf Folgendes reduziert werden: Was sollte das Elternteil eines Prozesses sein? Soll es zB eine Shell sein oder soll es der init
Prozess sein, also der Prozess mit PID 1
?
init
- worauf könnte die antwort lauten ... vielleicht? es hängt davon ab, wie / ob Sie mit ihm sprechen möchten, wasinit
Sie verwenden und wo sich die Datenkanäle befinden. Im Allgemeinen wird das Zeug dazu neigen, sich von selbst auszuarbeiten - dafürinit
ist es da. In jedem Fall normalerweise dann, wenn Sie einen Prozess dämonisiereninit
. Oder wenn Sie Auftragssteuerung möchten, aktuelle Shell.dmenu
und sehen, wie ich mit dem, was ich gelernt habe, zurechtkomme. Ich findeexec /path/to/Program & exit
oder/bin/bash -c /path/to/Program & exit
ganz brauchbar zu sein. Aber sie alle machen1
alsoinit
die Eltern vonProgram
denen, die mir recht sind, solange dies Sinn macht und keine*nix
Grundprinzipien verletzt .exec &
, denke ich. Normalerweise erledige ich meine Sachen nur vom Terminal aus. Vielleicht kann die Frage von Ben Crowell hier etwas nützen . Ich habe dort eine Antwort, aber alle sind sehr gut. Jedenfalls, wenn Sie einen Prozess im Hintergrund haben und sein Elternteil stirbt, wie:sh -c 'cat & kill $$'
Sie verwaisen ihn, und es kommt schließlich dazu, dass er geerntet wird. das ist die aufgabe von init - deshalb fallen sie alle darauf herein.systemd--bash--chromium
. Alle Methoden, die ich versuche, führen letztendlich zu einem Prozessbaum der folgenden Form,systemd--chromium
wenn ich Firefox aus der Shell spawne. Wie wird die Muschel hier dämonisiert? Es ist keinem Terminal zugeordnet.Antworten:
Nun, Sie scheinen ein ziemlich gutes Verständnis dafür zu haben. Um zu klären, was Sie haben,
sh -c /path/to/Program
ist ziemlich ähnlich zuWenn Sie einen neuen Shell-Prozess starten, geben Sie den Anwendungsbefehlspfad für die neue Shell an und lassen Sie die neue Shell dann beenden. Ich habe die neue Shell zu Illustrationszwecken mit einer anderen Eingabeaufforderung gezeigt. Dies würde im wirklichen Leben wahrscheinlich nicht passieren. Das Konstrukt ist vor allem dann nützlich, wenn Sie knifflige Aufgaben erledigen möchten, z. B. wenn Sie mehrere Befehle in ein Bundle einbinden, sodass sie wie ein einzelner Befehl aussehen (eine Art nicht benanntes Einmalskript) oder wenn Sie komplizierte Befehle erstellen, möglicherweise aus Shell-Variablen. Sie würden es selten nur zum Ausführen eines einzelnen Programms mit einfachen Argumenten verwenden.
sh -c "command"
2>&1
bedeutet, dass der Standardfehler zur Standardausgabe umgeleitet wird. Das hat nicht wirklich viel damit zu tun&
; Sie verwenden es eher, wenn ein Befehl Fehlermeldungen an den Bildschirm sendet, auch wenn Sie sagen, dass Sie die Fehlermeldungen in der Datei erfassen möchten.command > file
nohup.out
ist ein geringfügiger Nebeneffekt vonnohup
. Der Hauptzweck von ist die asynchrone Ausführung (allgemein bekannt als "im Hintergrund" oder als "Shell-unabhängiger Prozess", um Ihre Wörter zu verwenden) und die Konfiguration so, dass die Wahrscheinlichkeit größer ist, dass die Ausführung bei Ihnen fortgesetzt werden kann Beenden Sie die Shell (z. B. Abmelden), während der Befehl noch ausgeführt wird.nohup command &
command
bash(1)
und das Bash-Referenzhandbuch sind gute Informationsquellen.quelle
Es gibt verschiedene Möglichkeiten, ein Programm auszuführen und von einem Terminal zu trennen. Eine besteht darin, es im Hintergrund einer Subshell wie folgt auszuführen (durch
firefox
Ihr Lieblingsprogramm ersetzen ):Eine andere ist, den Prozess zu verleugnen:
Wenn Sie neugierig , wie App Werfer arbeiten,
dmenu
bietet 1 binäre und 2 Shell - Scripts:dmenu
,dmenu_path
unddmenu_run
, respectively.dmenu_run
leitet die Ausgabe vondmenu_path
in das Menü weiter, das wiederum in die$SHELL
Variable weiterleitet, auf die Ihre Variable eingestellt ist. Wenn es leer ist, wird es verwendet/bin/sh
.dmenu_path
ist etwas komplexer, enthält jedoch eine Liste der Binärdateien in Ihrer$PATH
Umgebungsvariablen und verwendet nach Möglichkeit einen Cache.Es ist nicht erforderlich, dass Programme in Shells ausgeführt werden. Eine andere Art zu schreiben
dmenu_run
, ohne in eine Shell zu pfeifen, wäre:quelle
Ich mag die Antwort von G-Man sehr. Aber ich antworte, weil ich denke, dass Sie Bedenken verwirren. Wie Wayne betont, lautet die beste Antwort "Was auch immer die gewünschten Ergebnisse erzielt".
In der Unix-Prozessverwaltung hat jeder Prozess ein übergeordnetes Element. Die einzige Ausnahme ist der
init
Prozess, der vom Betriebssystem beim Booten gestartet wird. Es ist normal, dass ein übergeordneter Prozess alle untergeordneten Prozesse mitnimmt, wenn er stirbt. Dies erfolgt durch Senden des SIGHUP-Signals an alle untergeordneten Prozesse. Die Standardbehandlung von SIGHUP beendet den Prozess.Das Shell-Spawnen von Benutzerprozessen unterscheidet sich nicht davon, wenn Sie die Fork- (2) / Exec- (3) -Aufrufe in der Sprache Ihrer Wahl codiert haben . Die Shell ist Ihr übergeordnetes Element. Wenn die Shell beendet wird (z. B. wenn Sie sich abmelden), werden die von ihr erzeugten untergeordneten Prozesse ebenfalls ausgeführt. Die Nuancen, die Sie beschreiben, sind nur Möglichkeiten, dieses Verhalten zu ändern.
exec /path/to/program
ist wie der Aufruf von exec (3) . Ja, es wird Ihre Shell durch ersetzenprogram
, wobei das übergeordnete Element, das die Shell gestartet hat , erhalten bleibt .sh -c /path/to/program
Art sinnlos erstellt ein Kind Shell-Prozess, der einen Kind-Prozess von erstellen wirdprogram
. Dies ist nur dann sinnvoll, wenn/path/to/program
es sich tatsächlich um eine Folge von Skriptanweisungen handelt und nicht um eine ausführbare Datei. (sh /path/to/script.sh
Kann verwendet werden, um ein Shell-Skript auszuführen, dem Ausführungsberechtigungen in einer minderwertigen Shell fehlen.)/path/to/program
Erstellt einen "Vordergrund" -Prozess, dh die Shell wartet, bis der Prozess abgeschlossen ist, bevor sie eine andere Aktion ausführt. Im Kontext eines Systemaufrufs ist dies wie bei fork (2) / exec (3) / waitpid (2) . Beachten Sie, dass das untergeordnete Element stdin / stdout / stderr vom übergeordneten Element erbt./path/to/program &
(Umleitung ignorieren) erzeugt einen "Hintergrundprozess". Der Prozess ist noch ein untergeordnetes Element der Shell, das übergeordnete Element wartet jedoch nicht auf den Abschluss.nohup /path/to/program
ruft nohup (1) auf, um das Senden von SIGHUP zu verhindern,program
wenn das steuernde Terminal geschlossen ist. Es ist eine Wahl, ob es im Vordergrund oder im Hintergrund ist (obwohl der Prozess am häufigsten im Hintergrund abläuft). Beachten Sie, dass diesnohup.out
nur die Ausgabe ist, wenn Sie stdout nicht anderweitig umleiten.Wenn Sie einen Prozess in den Hintergrund stellen und der übergeordnete Prozess abstirbt, geschieht Folgendes: Wenn das übergeordnete Terminal ein steuerndes Terminal ist , wird SIGHUP an die untergeordneten Terminals gesendet. Ist dies nicht der Fall, ist der Prozess möglicherweise "verwaist" und wird vom
init
Prozess geerbt .Wenn Sie Eingabe / Ausgabe / Fehler umleiten, verbinden Sie einfach die Dateideskriptoren, die jeder Prozess hat, mit anderen Dateien als denjenigen, die er von seinem übergeordneten Prozess erbt. Nichts davon wirkt sich auf den Prozessbesitz oder die Baumtiefe aus (es ist jedoch immer sinnvoll, alle 3 für Hintergrundprozesse von einem Terminal wegzuleiten).
Nach alledem denke ich nicht, dass Sie sich mit der Erstellung von Prozessen durch die Shell oder Sub-Shells oder Sub-Prozesse befassen sollten, es sei denn, es gibt ein spezifisches Problem, das Sie im Zusammenhang mit der Prozessverwaltung ansprechen.
quelle
sh -c /path/to/program
das Programm nicht als Shell-Skript aus, wenn die ausführbaren Bits fehlensh /path/to/program
.sh -c /path/to/program
wird nur eine Shell öffnen und/path/to/program
als Befehl in dieser Shell ausgeführt, was fehlschlägt, wenn sie nicht ausführbar ist.sh -c /path/to/program
Liest Befehle/path/to/program
als Eingabe in die Shell. Es ist nicht erforderlich, dass die Datei über die Ausführungsberechtigung verfügt, es sollte sich jedoch um ein Shell-Skript handelnsh /path/to/program
macht das. Gerade versucht , dass mir:echo echo hello world >abc.sh
, dannsh ./abc.sh
druckthello world
, währendsh -c ./abc.sh
sagtsh: ./abc.sh: Permission denied
(was dasselbe ist , als ob Sie laufen würde./abc.sh
. Direkt in der aktuellen Shell) Habe ich etwas verpasst? (Oder vielleicht habe ich mich im vorherigen Kommentar nicht gutsh -c _something_
ist dasselbe, als würde man nur_something_
an der Eingabeaufforderung tippen, außer dass die untergeordnete Shell erzeugt wird. Sie haben also Recht, dass es fehlschlägt, wenn das Ausführungsbit (als Datei) fehlt. Auf der anderen Seite können Sie eine Reihe von Shell-Befehlen wie bereitstellensh -c "echo hello world"
und es wird gut funktionieren. Es ist also nicht erforderlich, dass das von Ihnen eingegebene Ausführungsbit (oder sogar eine Datei) vorhanden ist, sondern nur, dass der Shell-Interpreter etwas damit anfangen kann.