Wie werden die Befehlszeilenargumente an einen laufenden Prozess auf Unix- / Linux-Systemen übergeben?

202

Unter SunOS gibt es einen pargsBefehl, der die Befehlszeilenargumente druckt, die an den laufenden Prozess übergeben werden.

Gibt es in anderen Unix-Umgebungen einen ähnlichen Befehl?

Hemant
quelle
4
tr \\0 ' ' < /proc/<pid>/cmdline
Dmitry Grigoryev

Antworten:

307

Es gibt mehrere Möglichkeiten:

ps -fp <pid>
cat /proc/<pid>/cmdline | sed -e "s/\x00/ /g"; echo

Es gibt mehr Infos /proc/<pid>unter Linux, schauen Sie einfach mal rein.

Bei anderen Unixen können die Dinge anders sein. Der psBefehl funktioniert überall, das /procZeug ist betriebssystemspezifisch. Zum Beispiel gibt es unter AIX kein cmdlineIn /proc.

markus_b
quelle
49
Unter Linux benötigen Sie wahrscheinlich -ww (dh ps -ww -fp <pid>), um eine breite Ausgabe anzugeben, da diese bei mehreren Befehlen möglicherweise abgeschnitten werden.
Silfheed
2
Die -wwOption ermöglicht den Zugriff auf vollständige Befehlszeilenargumente (so viel wie vom Kernel gespeichert wird). Siehe auch: Wie Solaris und BSD die nicht abgeschnittenen Befehlszeilenparameter für einen Prozess und ps-Optionen erhalten
GuruM
3
cat /proc/<pid>/cmdlineFunktioniert auch in Cygwin, wo cmd-Zeilenargumente psmit keiner Option angezeigt werden.
Lechup
3
Wenn Sie unter Linux nur das benötigen, argslautet der Befehl ps -o args -p <pid>und es wird nur das argsoder -o gedruckt, cmdwenn Sie nur das sehen müssen cmd. Der Versuch zu lesen /proc/<pid>/cmdlinefunktioniert nicht immer für Benutzer ohne Berechtigung. Das psDienstprogramm wird funktionieren.
Alvits
2
Hinweis: Die Länge von /proc/<pid>/cmdlineist begrenzt (fest auf den Wert des Kernelparameters PAGE_SIZE codiert), sodass längere Befehlszeilen immer noch abgeschnitten angezeigt werden! Weitere Informationen finden Sie unter stackoverflow.com/questions/199130/… . Sie können Ihre Kernel-Einstellung mit abfragen getconf PAGE_SIZE, es ist normalerweise 4096.
t0r0X
61

Dies wird den Trick tun:

xargs -0 < /proc/<pid>/cmdline

Ohne die xargs gibt es keine Leerzeichen zwischen den Argumenten, da sie in NULs konvertiert wurden.

Michael Böckling
quelle
3
Dies kann auf verkürzt werden xargs -0 < /proc/<pid>/cmdline.
Slm
Es schneidet meine Ausgabe immer noch ab. Irgendwelche Ratschläge?
Johnsam
Nie eine Kürzung bemerkt - können Sie ein Beispiel geben?
Michael Böckling
Auf diese Weise können Sie nicht sagen, ob es sich um einen Inline-Bereich oder eine Argumentgrenze handelt.
ivan_pozdeev
19

Vollständige Befehlszeile

Für Linux & Unix System können Sie ps -ef | grep process_namedie vollständige Befehlszeile abrufen.

Wenn Sie auf SunOS-Systemen die vollständige Befehlszeile erhalten möchten, können Sie diese verwenden

/usr/ucb/ps -auxww | grep -i process_name

Um die vollständige Befehlszeile zu erhalten, müssen Sie Superuser werden.

Liste der Argumente

pargs -a PROCESS_ID

gibt eine detaillierte Liste der an einen Prozess übergebenen Argumente. Das Array von Argumenten wird folgendermaßen ausgegeben:

argv[o]: first argument
argv[1]: second..
argv[*]: and so on..

Ich habe keinen ähnlichen Befehl für Linux gefunden, aber ich würde den folgenden Befehl verwenden, um eine ähnliche Ausgabe zu erhalten:

tr '\0' '\n' < /proc/<pid>/environ
LOGAN
quelle
14

Unter Linux

cat /proc/<pid>/cmdline

Sie erhalten die Befehlszeile des Prozesses (einschließlich Argumente), wobei jedoch alle Leerzeichen in NUL-Zeichen geändert wurden.

Lothar
quelle
3
Leerzeichen werden nicht entfernt, sondern durch NULs ersetzt.
Bdonlan
@bdonlan Ah, das habe ich nicht überprüft. Guter Fang!
Lothar
4
xargs -0 echo </ proc / <pid> / cmdline. Sie können dies auch mit / proc / <pid> / environ tun, obwohl Sie dafür möglicherweise -n 1 hinzufügen möchten.
Camh
Auf meinem System gibt es kein / proc-Dateisystem :( irgendeine andere Lösung?
Hemant
Meins ist ein Java-Prozess mit langen, langen, langen Parametern. Es schneidet meine Ausgabe immer noch ab. Irgendwelche Ratschläge?
Johnsam
14

Sie können verwenden pgrepmit -f(vollständige Befehlszeile) und -l(lange Beschreibung):

pgrep -l -f PatternOfProcess

Diese Methode unterscheidet sich entscheidend von allen anderen Antworten: Sie funktioniert unter CygWin , sodass Sie damit die vollständige Befehlszeile aller unter Windows ausgeführten Prozesse abrufen können (als erhöht ausführen, wenn Sie Daten zu einem erhöhten / Administrator-Prozess wünschen). . Jede andere Methode, um dies unter Windows zu tun, ist ( zum Beispiel ) umständlicher .
Außerdem: In meinen Tests war der pgrep-Weg das einzige System, das den vollständigen Pfad für Skripte erhalten hat, die in CygWins Python ausgeführt werden .

Sopalajo de Arrierez
quelle
Dieser druckt tatsächlich auch den ursprünglichen ausführbaren Namen:$ exec -a fakename bash & [1] 14102 [1]+ Stopped exec -a fakename bash $ xargs -0 < /proc/14102/cmdline; fakename $ pgrep -l -f fakename; 14102 bash
Unhammer
Funktioniert bei mir nicht mit pgrep from procps-ng 3.3.15und 3.3.12. Druckt einfach den PID- und Prorgam-Namen ohne Argumente.
Socowi
4

Eine andere Variante des Druckens /proc/PID/cmdlinemit Leerzeichen unter Linux ist:

cat -v /proc/PID/cmdline | sed 's/\^@/\ /g' && echo

Auf diese Weise werden NULL-Zeichencat gedruckt als^@ und anschließend durch ein Leerzeichen ersetzt sed. echodruckt eine neue Zeile.

Diego
quelle
Zu Ihrer Information , Sie können auch cat -v / proc / PID / cmdline | verwenden sed 's / \ ^ @ / \ n / g' . Dadurch wird das Nullzeichen durch ein Zeilenumbruchzeichen ersetzt. Dabei wird jedes Argument in einer eigenen Zeile gedruckt. Auf diese Weise ist es einfacher, ein Argument von einem anderen zu unterscheiden.
TSJNachos117
2

Sie können einfach verwenden:

ps -o args= -f -p ProcessPid
Mitar
quelle
2

Anstatt mehrere Befehle zum Bearbeiten des Streams zu verwenden, verwenden Sie einfach einen - tr übersetzt ein Zeichen in ein anderes:

tr '\0' ' ' </proc/<pid>/cmdline
Tom Evans
quelle
1

Zusätzlich zu allen oben genannten Möglichkeiten zum Konvertieren des Textes wird die Ausgabe standardmäßig in separaten Zeilen ausgeführt, wenn Sie einfach "Zeichenfolgen" verwenden. Mit dem zusätzlichen Vorteil, dass möglicherweise auch keine Zeichen angezeigt werden, die Ihr Terminal verschlüsseln könnten.

Beide geben in einem Befehl aus:

Zeichenfolgen / proc // cmdline / proc // environ

Die eigentliche Frage ist ... gibt es eine Möglichkeit, die tatsächliche Befehlszeile eines Prozesses unter Linux anzuzeigen, der so geändert wurde, dass die cmdline den geänderten Text anstelle des tatsächlich ausgeführten Befehls enthält.

Timothy J. Biggs
quelle
1

Unter Solaris

     ps -eo pid,comm

Ähnliches kann auf Unix-ähnlichen Systemen verwendet werden.

HuntM
quelle
1

Unter Linux mit Bash als zitierte Argumente ausgeben, damit Sie den Befehl bearbeiten und erneut ausführen können

</proc/"${pid}"/cmdline xargs --no-run-if-empty -0 -n1 \
    bash -c 'printf "%q " "${1}"' /dev/null; echo

Unter Solaris mit bash (getestet mit 3.2.51 (1) -release) und ohne gnu userland:

IFS=$'\002' tmpargs=( $( pargs "${pid}" \
    | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
    | tr '\n' '\002' ) )
for tmparg in "${tmpargs[@]}"; do
    printf "%q " "$( echo -e "${tmparg}" )"
done; echo

Linux Bash Beispiel (Einfügen in Terminal):

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &

## recover into eval string that assigns it to argv_recovered
eval_me=$(
    printf "argv_recovered=( "
    </proc/"${!}"/cmdline xargs --no-run-if-empty -0 -n1 \
        bash -c 'printf "%q " "${1}"' /dev/null
    printf " )\n"
)

## do eval
eval "${eval_me}"

## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

Ausgabe:

MATCH

Solaris Bash Beispiel:

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &
pargs "${!}"
ps -fp "${!}"

declare -p tmpargs
eval_me=$(
    printf "argv_recovered=( "
    IFS=$'\002' tmpargs=( $( pargs "${!}" \
        | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
        | tr '\n' '\002' ) )
    for tmparg in "${tmpargs[@]}"; do
        printf "%q " "$( echo -e "${tmparg}" )"
    done; echo
    printf " )\n"
)

## do eval
eval "${eval_me}"


## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

Ausgabe:

MATCH
Iwan Aucamp
quelle
0

Wenn Sie eine möglichst lange Zeit erhalten möchten (nicht sicher, welche Grenzen es gibt), ähnlich wie bei Solaris ' Pargs , können Sie diese unter Linux und OSX verwenden:

ps -ww -o pid,command [-p <pid> ... ]
pourhaus
quelle
-1

Versuchen ps -n in einem Linux-Terminal. Dies wird zeigen:

1.Alle Prozesse RUNNING , ihre Befehlszeile und ihre PIDs

  1. Das Programm leitet die Prozesse ein.

Danach wissen Sie, welchen Prozess Sie beenden müssen

repzero
quelle