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