it-swarm.com.de

Wie bekomme ich einen Überblick über den gerade gestarteten Prozess?

Ich möchte den Prozess starten (z. B. myCommand) und seine PID erhalten (um ihn später beenden zu können).

Ich habe versucht, ps und nach Namen zu filtern, aber ich kann den Prozess nicht nach Namen unterscheiden

myCommand
ps ux | awk '/<myCommand>/ {print $2}' 

Weil Prozessnamen nicht eindeutig sind.

Ich kann den Prozess ausführen durch:

myCommand &

Ich habe festgestellt, dass ich diese PID erhalten kann durch:

echo $!

Gibt es eine einfachere Lösung?

Ich würde gerne myCommand ausführen und seine PID als Ergebnis eines einzeiligen Befehls erhalten.

78
rafalmag

Was kann einfacher sein als echo $!? Als eine Zeile:

myCommand & echo $!
86
Jacek Konieczny

Schließen Sie den Befehl in ein kleines Skript ein

#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file
30
user9517

Sie können sh -c Und exec verwenden, um die PID des Befehls sogar zu erhalten, bevor er ausgeführt wird.

Um myCommand zu starten, damit die PID gedruckt wird, bevor sie ausgeführt wird, können Sie Folgendes verwenden:

sh -c 'echo $$; exec myCommand'

Wie es funktioniert:

Dies startet eine neue Shell, druckt die PID dieser Shell und verwendet dann das eingebaute exec, um die Shell durch Ihren Befehl zu ersetzen . Sicherstellen, dass es die gleiche PID hat. Wenn Ihre Shell einen Befehl mit dem eingebauten exec ausführt, wird Ihre Shell tatsächlich wird dieser Befehl als das üblichere Verhalten eine neue Kopie von sich selbst zu forken, die eine eigene separate PID hat und dann zum Befehl wird.

Ich finde das viel einfacher als Alternativen, die asynchrone Ausführung (mit &), Jobsteuerung oder Suche mit ps beinhalten. Diese Ansätze sind in Ordnung, aber wenn Sie keinen bestimmten Grund haben, sie zu verwenden - zum Beispiel wird der Befehl möglicherweise bereits ausgeführt. In diesem Fall wäre es sinnvoll, nach seiner PID zu suchen oder die Jobsteuerung zu verwenden -, empfehle ich, diesen Weg zuerst in Betracht zu ziehen. (Und ich würde sicherlich nicht in Betracht ziehen, ein komplexes Skript oder ein anderes Programm zu schreiben, um dies zu erreichen).

Diese Antwort enthält ein Beispiel für diese Technik.


Teile dieses Befehls konnten gelegentlich weggelassen werden, aber normalerweise nicht.

Selbst wenn die von Ihnen verwendete Shell im Bourne-Stil ist und daher das mit dieser Semantik integrierte exec unterstützt, sollten Sie im Allgemeinen nicht versuchen, die Verwendung von sh -c (Oder einem gleichwertigen Element) zum Erstellen eines zu vermeiden neuer, separater Shell-Prozess für diesen Zweck, weil:

  • Sobald die Shell zu myCommand geworden ist, wartet keine Shell darauf, nachfolgende Befehle auszuführen. sh -c 'echo $$; exec myCommand; foo Kann nicht versuchen, foo auszuführen, nachdem er sich durch myCommand ersetzt hat. Wenn Sie kein Skript schreiben, das dies als letzten Befehl ausführt, können Sie echo $$; exec myCommand Nicht einfach in einer Shell verwenden, in der Sie andere Befehle ausführen.
  • Sie können hierfür keine nterschale verwenden. (echo $$; exec myCommand) Ist möglicherweise syntaktisch besser als sh -c 'echo $$; exec myCommand', Wenn Sie jedoch $$ In () Ausführen, wird die PID der übergeordneten Shell angegeben , nicht von der Unterschale selbst. Es ist jedoch die PID der Subshell, die die PID des neuen Befehls ist. Einige Shells bieten ihre eigenen nicht portierbaren Mechanismen zum Ermitteln der PID der Subshell, die Sie dafür verwenden können. Insbesondere in Bash 4 , (echo $BASHPID; exec myCommand) Funktioniert.

Beachten Sie schließlich, dass einige Shells ein Optimierung ausführen, wobei sie einen Befehl wie von exec ausführen (dh sie verzichten zuerst auf das Gabeln), wenn bekannt ist, dass die Shell dies nicht muss mach danach alles. Einige Shells versuchen dies immer dann, wenn es der letzte Befehl ist, der ausgeführt wird, während andere dies nur tun, wenn vor oder nach dem Befehl keine anderen Befehle vorhanden sind, und andere dies überhaupt nicht tun. Der Effekt ist, dass wenn Sie vergessen, exec zu schreiben und nur sh -c 'echo $$; myCommand' Verwenden, es Ihnen manchmal das Recht gibt PID auf einigen Systemen mit einigen Shells. Ich empfehle, sich niemals auf ein solches Verhalten zu verlassen und stattdessen immer exec einzuschließen, wenn Sie dies benötigen.

24
Eliah Kagan

Ich kenne keine einfachere Lösung, benutze aber kein $! gut genug? Sie können den Wert jederzeit einer anderen Variablen zuweisen, wenn Sie ihn später benötigen, wie von anderen angegeben.

Als Randnotiz können Sie anstelle von Piping von ps pgrep oder pidof verwenden.

7
carlpett

verwenden Sie exec aus einem Bash-Skript, nachdem Sie die PID in einer Datei registriert haben:

beispiel:

angenommen, Sie haben ein Skript mit dem Namen "forever.sh", das Sie mit den Argumenten p1, p2, p3 ausführen möchten

forever.sh Quellcode:

#!/bin/sh

while [ 1 -lt 2 ] ; do
    logger "$0 running with parameters \"[email protected]\""
    sleep 5
done

erstellen Sie eine reaper.sh:

#!/bin/sh

echo $$ > /var/run/$1.pid
exec "[email protected]"

laufe für immer.sh durch reaper.sh:

./reaper.sh ./forever.sh p1 p2 p3 p4 &

forever.sh protokolliert lediglich alle 5 Sekunden eine Zeile in syslog

sie haben jetzt die PID in /var/run/forever.sh.pid

cat /var/run/forever.sh.pid 
5780

und forever.sh läuft aok. syslog grep:

Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"

sie können es in der Prozesstabelle sehen:

ps axuwww|grep 'forever.sh p1' |grep -v grep
root      5780  0.0  0.0   4148   624 pts/7    S    16:07   0:00 /bin/sh ./forever.sh p1 p2 p3 p4
5
user237419

In der Bash-Shell könnte eine Alternative zu $! Das integrierte jobs -p Sein. In einigen Fällen wird ! In $! Vor (oder anstelle) der Variablenerweiterung von der Shell interpretiert, was zu unerwarteten Ergebnissen führt.

Dies funktioniert beispielsweise nicht:

((yourcommand) & echo $! >/var/run/pidfile)

während dies wird:

((yourcommand) & jobs -p >/var/run/pidfile)
3
mustaccio

Dies ist eine hackige Antwort und wird wahrscheinlich für die meisten Menschen nicht funktionieren. Es ist auch ein großes Sicherheitsrisiko. Tun Sie es also nur, wenn Sie sicher sind, dass Sie sicher sind und die Eingaben bereinigt sind und ... nun, Sie haben die Idee.

Kompilieren Sie das kleine C-Programm hier in eine Binärdatei namens start (oder was auch immer Sie wollen) und führen Sie dann Ihr Programm als ./start your-program-here arg0 arg1 arg2 ... Aus.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    if (argc >= 2)
    {
        printf("%lu\n", (long unsigned) getpid());
        if (execvp(argv[1], &argv[1]) < 0)
        {
            perror(NULL);
            return 127;
        }
    }
    return 0;
}

Kurz gesagt, dies druckt die PID auf stdout und lädt dann Ihr Programm in den Prozess. Es sollte immer noch die gleiche PID haben.

1
tonysdg

Sie können etwas verwenden wie:

$ myCommand ; pid=$!

Oder

$ myCommand && pid=$!

Die beiden Befehle können Gelenke mit ; Oder && Sein. Im zweiten Fall wird die PID nur gesetzt, wenn der erste Befehl erfolgreich ist. Sie können die Prozess-ID von $pid Abrufen.

1
Khaled