Unter Linux mit dem ps
ab procps(-ng)
:
ps -fwwp 2755
In Linux-Versionen vor 4.2 ist es jedoch immer noch begrenzt (durch den Kernel (/proc/2755/cmdline
) bis 4k) und Sie können nicht mehr bekommen, außer indem Sie den Prozess bitten, es Ihnen mitzuteilen, oder einen Debugger verwenden.
$ sh -c 'sleep 1000' $(seq 4000) &
[1] 31149
$ gdb -p $! /bin/sh
[...]
Attaching to program: /bin/dash, process 31149
[...]
(gdb) bt
#0 0x00007f40d11f40aa in wait4 () at ../sysdeps/unix/syscall-template.S:81
[...]
#7 0x00007f40d115c995 in __libc_start_main (main=0x4022c0, argc=4003, ubp_av=0x7fff5b9f5a88, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff5b9f5a78)
at libc-start.c:260
#8 0x00000000004024a5 in ?? ()
#9 0x00007fff5b9f5a78 in ?? ()
#10 0x0000000000000000 in ?? ()
(gdb) frame 7
#7 0x00007f40d115c995 in __libc_start_main (main=0x4022c0, argc=4003, ubp_av=0x7fff5b9f5a88, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff5b9f5a78)
at libc-start.c:260
(gdb) x/4003s *ubp_av
0x7fff5b9ff83e: "sh"
0x7fff5b9ff841: "-c"
0x7fff5b9ff844: "sleep 1000"
0x7fff5b9ff84f: "1"
0x7fff5b9ff851: "2"
[...]
0x7fff5ba04212: "3999"
0x7fff5ba04217: "4000"
Um das 4. Argument mit bis zu 5000 Zeichen zu drucken:
(gdb) set print elements 5000
(gdb) p ubp_av[3]
Wenn Sie etwas Unaufdringliches wünschen, können Sie versuchen, die Informationen von /proc/2755/mem
abzurufen (Beachten Sie, dass wenn der kernel.yama.ptrace_scope
nicht auf 0 gesetzt ist, benötigen Sie dafür Superuser-Berechtigungen). Das unten funktioniert für mich (druckt alle Argumente und Umgebungsvariablen), aber es gibt nicht viel Garantie, würde ich denken (die Behandlung von Fehlern und unerwarteten Eingaben bleibt dem Leser als Übung überlassen):
$ perl -e '$p=shift;open MAPS, "/proc/$p/maps";
($m)=grep /\[stack\]/, <MAPS>;
($a,$b)=map hex, $m =~ /[\da-f]+/g;
open MEM, "/proc/$p/mem" or die "open mem: $!";
seek MEM,$a,0; read MEM, $c,$b-$a;
print((split /\0{2,}/,$c)[-1])' "$!" | tr \\0 \\n | head
sh
-c
sleep 1000
1
2
3
4
5
6
7
(ersetzen Sie "$!"
mit der Prozess-ID). Das Obige nutzt die Tatsache, dass Linux die Zeichenfolgen setzt, auf die durch argv[]
verwiesen wird , envp[]
und der ausgeführte Dateiname am Ende des Stapels des Prozesses.
Das Obige sucht in diesem Stapel nach der untersten Zeichenfolge zwischen zwei Sätzen von zwei oder mehr aufeinanderfolgenden NUL-Bytes. Es funktioniert nicht, wenn eines der Argumente oder env-Strings leer ist, da Sie dann eine Folge von 2 NUL-Bytes in der Mitte dieser argv oder envp haben. Außerdem wissen wir nicht, wo die argv-Strings aufhören und wo die envp-Strings beginnen.
Ein Workaround dafür wäre, diese Heuristik zu verfeinern, indem man rückwärts nach dem tatsächlichen Inhalt von argv[]
sucht (die Zeiger). Das Folgende funktioniert zumindest auf der i386- und amd64-Architektur für ausführbare ELF-Dateien:
perl -le '$p=shift;open MAPS, "/proc/$p/maps";
($m)=grep /\[stack\]/, <MAPS>;
($a,$b)=map hex, $m =~ /[\da-f]+/g;
open MEM, "/proc/$p/mem" or die "open mem: $!";
seek MEM,$a,0; read MEM, $c,$b-$a;
$c =~ /.*\0\0\K[^\0].*\0[^\0]*$/s;
@a=unpack"L!*",substr$c,0,$-[0];
for ($i = $#a; $i >=0 && $a[$i] != $a+$-[0];$i--) {}
for ($i--; $i >= 0 && ($a[$i]>$a || $a[$i]==0); $i--) {}
$argc=$a[$i++];
print for unpack"(Z*)$argc",substr$c,$a[$i]-$a;' "$!"
Im Grunde macht es dasselbe wie oben, aber sobald es die erste Zeichenfolge von argv[]
gefunden hat (oder mindestens einer der argv[]
oder envp[]
Zeichenfolgen, wenn es Leerzeichen gibt), kennt es seine Adresse, also sucht es rückwärts im obersten Rest des Stapels nach einem Zeiger mit demselben Wert. Dann schaut es weiter rückwärts, bis es eine Zahl findet, die kein Zeiger auf diese sein kann, und das ist argc
. Dann ist die nächste Ganzzahl argv[0]
. Und wissend argv[0]
und argc
, kann es die Liste der Argumente anzeigen.
Das funktioniert nicht, wenn der Prozess auf seine argv[]
geschrieben hat möglicherweise Überschreiben einiger NUL-Trennzeichen oder wenn argc
ist 0 (argc
ist im Allgemeinen mindestens 1, um argv[0]
einzuschließen ), sollte aber im allgemeinen Fall zumindest für ausführbare ELF-Dateien funktionieren.
In 4.2 und neuer, /proc/<pid>/cmdline
nicht mehr abgeschnitten, sondern ps
selbst hat eine maximale Anzeigebreite von 128 KB.
Fügen Sie ein oder zwei -w
hinzu Flaggen. Es macht die Ausgabe breiter. z.B. ps auxww
.
In Linux Kernel 4.2 und neuer, /proc/<pid>/cmdline
wird nicht mehr abgeschnitten und Folgendes funktioniert gut:
xargs -0 printf '%s\n' < /proc/2755/cmdline