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
pgrep
So verwenden :
if ! pgrep -u $USER top >/dev/null 2>&1; then
exec top
fi
Erläuterung:
- Das
pgrep
Dienstprogramm 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.$USER
ist eine Standard-Shell-Variable. Wenn diese aus irgendeinem Grund nicht definiert ist, versuchen Sie$LOGNAME
stattdessen, und wenn dies fehlschlägt, verwenden Sie$( id -n -u )
(aber an diesem Punkt müssen Sie sich fragen, was los ist, denn$LOGNAME
istAucheine 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, exec
muss die Shell gemäß der Frage des OP ersetzt werden.
sh
Dies sollte in allen kompatiblen Shells funktionieren .
BEARBEITEN: Die pgrep
Implementierung auf BSD-Systemen (OS X, OpenBSD, ...) verfügt über eine -q
Option, mit der alle Ausgaben verworfen werden, aber pgrep
unter 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 lockfile
oder verwenden flock
. Zum Beispiel durch Hinzufügen
flock -n /tmp/top -c top
mit .bashrc
/ .zshrc
stellen Sie sicher, dass nur die erste Instanz der Shell den top
Befehl 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, mytop
wann immer du willst.
Antwort3
Das pgrep
ist zwar der richtige Weg, aber es gibt einige Fallstricke. Sie müssen diese -q
Option nicht verwenden, da Sie die Ausgabe umleiten können, pgrep
um 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 USER
Umgebungsvariable 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 USER
es sich um eine von vielen bekannten Variablen handelt (siehe Anmerkung in8.1 Definition der Umgebungsvariablen).
Dies läuft top
alsselbst, natürlich. Wenn Sie es als ausführen möchtenWurzel, dann könnten Sie $USER
in ändern root
und dann top
entweder sudo
(bevorzugt) oder ausführen su
. Keines von beiden ist in POSIX (siehe Liste). Letzteres ( su
) ist auf Unix-ähnlichen Systemen überall verfügbar, sudo
wird 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.