GNU/Linux >> Linux Esercitazione >  >> Linux

ps:il comando completo è troppo lungo

Su Linux, con ps da procps(-ng) :

ps -fwwp 2755

Nelle versioni di Linux precedenti alla 4.2, è comunque ancora limitato (dal kernel (/proc/2755/cmdline ) a 4k) e non puoi ottenere di più se non chiedendo al processo di comunicartelo o utilizzando un debugger.

$ 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"

Per stampare il 4° argomento con un massimo di 5000 caratteri:

(gdb) set print elements 5000
(gdb) p ubp_av[3]

Se vuoi qualcosa di non invadente, puoi provare a ottenere le informazioni da /proc/2755/mem (nota che se kernel.yama.ptrace_scope non è impostato su 0, avrai bisogno dei permessi di superutente per quello). Questo di seguito funziona per me (stampa tutti gli argomenti e le variabili d'ambiente), ma non c'è molta garanzia che penserei (l'errore e la gestione dell'input imprevisto sono lasciati come esercizio al lettore):

$ 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

(sostituisci "$!" con l'ID del processo). Quanto sopra sfrutta il fatto che Linux mette le stringhe puntate da argv[] , envp[] e il nome del file eseguito in fondo allo stack del processo.

Quanto sopra cerca in quello stack la stringa più in basso tra due set di due o più byte NUL consecutivi. Non funziona se uno qualsiasi degli argomenti o delle stringhe env è vuoto, perché in tal caso avrai una sequenza di 2 byte NUL nel mezzo di quegli argv o envp. Inoltre, non sappiamo dove finiscono le stringhe argv e dove iniziano quelle envp.

Una soluzione potrebbe essere quella di perfezionare quell'euristica cercando all'indietro il contenuto effettivo di argv[] (i puntatori). Quanto segue funziona almeno sull'architettura i386 e amd64 per gli eseguibili ELF:

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;' "$!"

Fondamentalmente, fa lo stesso come sopra, ma una volta trovata la prima stringa di argv[] (o almeno uno dei argv[] o envp[] stringhe se ci sono vuoti), conosce il suo indirizzo, quindi guarda indietro nel resto superiore dello stack per un puntatore con lo stesso valore. Quindi continua a guardare indietro finché non trova un numero che non può essere un puntatore a quelli, e questo è argc . Quindi il numero intero successivo è argv[0] . E conoscendo argv[0] e argc , può visualizzare l'elenco degli argomenti.

Ciò non funziona se il processo ha scritto nel suo argv[] possibilmente sovrascrivendo alcuni delimitatori NUL o se argc è 0 (argc generalmente è almeno 1 per includere argv[0] ) ma dovrebbe funzionare nel caso generale almeno per gli eseguibili ELF.

Nella versione 4.2 e successive, /proc/<pid>/cmdline non è più troncato, ma ps stesso ha una larghezza di visualizzazione massima di 128K.


Aggiungi uno o due -w bandiere. Rende l'output più ampio. per esempio. ps auxww .


Nel kernel Linux 4.2 e successivi, /proc/<pid>/cmdline non è più troncato e quanto segue funziona correttamente:

xargs -0 printf '%s\n' < /proc/2755/cmdline

Linux
  1. Perché un lungo ritardo dopo il comando non trovato?

  2. Comando Sudo dopo una lunga chiamata di sonno senza richiedere nuovamente la password Sudo?

  3. Comando Linux mv

  4. Linux du comando

  5. Impossibile rimuovere i file dalla directory con l'errore "Elenco di argomenti troppo lungo"

Comando W in Linux

Al comando in Linux

comando ifconfig

Linux top -c per mostrare il comando completo

Perché il comando sudo richiede molto tempo per essere eseguito?

Limite di caratteri della riga di comando di Linux