GNU/Linux >> Belajar Linux >  >> Linux

ps:perintah penuh terlalu panjang

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

Linux
  1. Mengapa Penundaan Lama Setelah Perintah Tidak Ditemukan?

  2. Ubuntu – Daftar Argumen Terlalu Panjang?

  3. Perintah Sudo Setelah Panggilan Tidur Panjang Tanpa Meminta Kata Sandi Sudo?

  1. Tidak Dapat Menghapus File Dari Direktori dengan Kesalahan "Daftar argumen terlalu panjang"

  2. Melihat output penuh dari perintah PS

  3. Kesalahan SFTP Pesan yang diterima terlalu lama

  1. Perintah mv Linux

  2. Daftar argumen kesalahan terlalu panjang untuk perintah rm, cp, mv

  3. OSError terputus-putus:[Errno 7] Daftar argumen terlalu panjang dengan perintah pendek (~125 karakter)