GNU/Linux >> LINUX-Kenntnisse >  >> Linux

ps:vollständiger Befehl ist zu lang

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

Linux
  1. Ubuntu – Argumentliste zu lang?

  2. Sudo-Befehl nach langem Schlafanruf ohne erneute Aufforderung zum Sudo-Passwort?

  3. Linux-IP-Befehl

  4. Linux-cd-Befehl

  5. Anzeigen der vollständigen Ausgabe des PS-Befehls

W-Befehl unter Linux

Bei Befehl unter Linux

ifconfig-Befehl

Fehler Argumentliste zu lang für rm-, cp-, mv-Befehle

Intermittierender OSError:[Errno 7] Argumentliste zu lang mit kurzem Befehl (~125 Zeichen)

Linux top -c um den vollständigen Befehl anzuzeigen