Di Linux, dengan ps
dari procps(-ng)
:
ps -fwwp 2755
Di versi Linux sebelum 4.2, ini masih dibatasi (oleh kernel (/proc/2755/cmdline
) ke 4k) dan Anda tidak bisa mendapatkan lebih banyak kecuali dengan meminta proses untuk memberitahukannya kepada Anda atau menggunakan 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"
Untuk mencetak argumen ke-4 hingga 5000 karakter:
(gdb) set print elements 5000
(gdb) p ubp_av[3]
Jika Anda menginginkan sesuatu yang tidak mengganggu, Anda dapat mencoba dan mendapatkan informasi dari /proc/2755/mem
(perhatikan bahwa jika kernel.yama.ptrace_scope
tidak disetel ke 0, Anda memerlukan izin pengguna super untuk itu). Ini di bawah ini berfungsi untuk saya (mencetak semua argumen dan variabel lingkungan), tetapi tidak banyak jaminan yang saya pikirkan (kesalahan dan penanganan input yang tidak terduga dibiarkan sebagai latihan untuk pembaca):
$ 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
(ganti "$!"
dengan proses id). Di atas menggunakan fakta bahwa Linux menempatkan string yang ditunjuk oleh argv[]
, envp[]
dan nama file yang dieksekusi di bagian bawah tumpukan proses.
Di atas terlihat di tumpukan itu untuk string paling bawah di antara dua set dua atau lebih NUL byte berturut-turut. Tidak berfungsi jika salah satu argumen atau string env kosong, karena Anda akan memiliki urutan 2 byte NUL di tengah argv atau envp tersebut. Selain itu, kami tidak tahu di mana string argv berhenti dan di mana string envp dimulai.
Solusi untuk itu adalah menyempurnakan heuristik itu dengan melihat ke belakang untuk konten sebenarnya dari argv[]
(penunjuk). Ini di bawah berfungsi pada arsitektur i386 dan amd64 setidaknya untuk executable 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;' "$!"
Pada dasarnya, ini sama seperti di atas, tetapi setelah menemukan string pertama argv[]
(atau setidaknya salah satu dari argv[]
atau envp[]
string jika ada yang kosong), ia mengetahui alamatnya, jadi ia melihat ke belakang di bagian atas tumpukan untuk penunjuk dengan nilai yang sama. Kemudian terus melihat ke belakang hingga menemukan angka yang tidak bisa menjadi penunjuk ke angka tersebut, yaitu argc
. Maka bilangan bulat berikutnya adalah argv[0]
. Dan mengetahui argv[0]
dan argc
, ini dapat menampilkan daftar argumen.
Itu tidak berfungsi jika proses telah menulis ke argv[]
mungkin mengesampingkan beberapa pembatas NUL atau jika argc
adalah 0 (argc
umumnya minimal 1 untuk memasukkan argv[0]
) tetapi harus berfungsi dalam kasus umum setidaknya untuk executable ELF.
Di 4.2 dan yang lebih baru, /proc/<pid>/cmdline
tidak lagi terpotong, melainkan ps
sendiri memiliki lebar tampilan maksimum 128K.
Tambahkan satu atau dua -w
bendera. Itu membuat output lebih luas. misalnya ps auxww
.
Di kernel Linux 4.2 dan yang lebih baru, /proc/<pid>/cmdline
tidak lagi terpotong dan yang berikut berfungsi dengan baik:
xargs -0 printf '%s\n' < /proc/2755/cmdline