Wie erkenne ich, ob ein Programm ausgeführt wird, wenn ich eine Shell starte und das Programm starte, sofern es nicht bereits ausgeführt wird?

Wie erkenne ich, ob ein Programm ausgeführt wird, wenn ich eine Shell starte und das Programm starte, sofern es nicht bereits ausgeführt wird?

Wenn ich eine Shell starte, in meinem Fall bash und/oder zsh, welche Zeilen muss ich zu .zshrc und/oder .bashrc hinzufügen, um zu prüfen, ob ein Programm bereits ausgeführt wird, und es zu starten, wenn das Programm nicht bereits ausgeführt wird?

Beispiel: Ich starte eine neue Zsh-Shell. Wenn top noch nicht läuft, möchte ich top starten und die Shell übernehmen lassen. Wenn top bereits in einem anderen Fenster läuft, möchte ich, dass .zshrc weiter geladen wird und mir ein offenes Terminal gibt.

16.6. Aktualisierung:

if ! pgrep -U $USER top >/dev/null; then
exec top
fi

Das obige Skript erfüllt meine Anforderung. Das Flag -q würde bei mir nicht funktionieren, da -q auf meinem System keine Option ist. Daher musste ich die PID nach /dev/null weiterleiten. Vielen Dank, mveroone, Kusalananda und Thomas Dickey.

Ich habe einige Funktionserweiterungen, die über den Rahmen der ursprünglichen Frage hinausgehen. Angenommen, ich befinde mich auf einem Einzelbenutzersystem, auf dem ich Root-Rechte erlangen kann, ohne ein Passwort eingeben zu müssen. Wie kann ich top automatisch als Root ausführen, wenn dies erforderlich ist?

6-18 Ok, das Feature Creep-Problem bei der Übergabe eines Befehls als Root ist behoben. Ich verwende dies, um mehrere

Vielen Dank für all die ausführlichen Antworten.

Antwort1

pgrepSo verwenden :

if ! pgrep -u $USER top >/dev/null 2>&1; then
    exec top
fi

Erläuterung:

  • Das pgrepDienstprogramm wird mit einem Exitcode von Null beendet, wenn der Befehl ausgeführt wird. Negieren Sie daher den Test.
  • Beschränken Sie es außerdem mit auf den aktuellen Benutzer -u $USER, damit es nicht aus irgendeinem Grund die Prozesse von jemand anderem aufgreift. $USERist eine Standard-Shell-Variable. Wenn diese aus irgendeinem Grund nicht definiert ist, versuchen Sie $LOGNAMEstattdessen, und wenn dies fehlschlägt, verwenden Sie $( id -n -u )(aber an diesem Punkt müssen Sie sich fragen, was los ist, denn $LOGNAMEistAucheine Standard-Shell-Variable).
  • Wir benötigen die Ausgabe von nicht pgrep, daher leiten wir die Standardausgabe und die Fehlerströme nach um /dev/null.

Wenn top(oder was auch immer) nicht ausgeführt wird, execmuss die Shell gemäß der Frage des OP ersetzt werden.

shDies sollte in allen kompatiblen Shells funktionieren .

BEARBEITEN: Die pgrepImplementierung auf BSD-Systemen (OS X, OpenBSD, ...) verfügt über eine -qOption, mit der alle Ausgaben verworfen werden, aber pgrepunter Linux gibt es dieses Flag anscheinend nicht. Verwenden Sie auf BSD-Systemen dies anstelle der etwas hässlichen Umleitung zu /dev/null.

Antwort2

Wenn das Programm immer von der Shell aus gestartet wird und Sie die volle Kontrolle darüber haben (d. h. es ist nicht in einem Drittanbieterprogramm fest codiert), können Sie einen Sperrmechanismus wie lockfileoder verwenden flock. Zum Beispiel durch Hinzufügen

flock -n /tmp/top -c top

mit .bashrc/ .zshrcstellen Sie sicher, dass nur die erste Instanz der Shell den topBefehl ausführt (es sei denn, Sie beenden sie und starten dann eine andere).

Möglicherweise möchten Sie eine Funktion erstellen, um den Befehl auch manuell starten zu können (nicht nur bei der Shell-Initialisierung):

mytop () { flock -n /tmp/$0 -c top; }

Und laufe einfach, mytopwann immer du willst.

Antwort3

Das pgrepist zwar der richtige Weg, aber es gibt einige Fallstricke. Sie müssen diese -qOption nicht verwenden, da Sie die Ausgabe umleiten können, pgrepum dies zu vermeiden:

pgrep -U $USER top >/dev/null || exec top

Die Fallstricke liegen darin, dass es sich nicht um ein Standardprogramm handelt. Sie müssen also bedenken, dass es möglicherweise nicht portierbar ist. Hier sind einige Manpage-Links, die Ihnen helfen können:

Die USERUmgebungsvariable ist besser etabliert, scheint aber nicht in der POSIX-Liste für die Shell enthalten zu sein (siehe2.5.3 Shell-Variablen). Vielmehr wird darauf hingewiesen, dass USERes sich um eine von vielen bekannten Variablen handelt (siehe Anmerkung in8.1 Definition der Umgebungsvariablen).

Dies läuft topalsselbst, natürlich. Wenn Sie es als ausführen möchtenWurzel, dann könnten Sie $USERin ändern rootund dann topentweder sudo(bevorzugt) oder ausführen su. Keines von beiden ist in POSIX (siehe Liste). Letzteres ( su) ist auf Unix-ähnlichen Systemen überall verfügbar, sudowird aber im Allgemeinen bevorzugt. Sie hätten also

pgrep -U root top >/dev/null || exec sudo top

Sofern Sie keine Konfiguration vorgenommen haben sudo, bei der kein Kennwort erforderlich ist, werden Sie beim Start Ihrer Shell zur Eingabe eines Kennworts aufgefordert top.

Antwort4

Ich würde einen Snippet wie diesen in meine .zshrc (oder eine andere) anhängen:

if pgrep -u $USER Programmname
Dann
    exec Programmname
fi

Vorbehalt :Ich habe diesen Code nicht getestet. Bitte verwenden Sie ihn nicht als Root oder für den einzigen Benutzer, den Sie auf einem Server haben. Stellen Sie sicher, dass Sie ihn wiederherstellen können, wenn er fehlschlägt.

verwandte Informationen