GNU/Linux >> Tutoriales Linux >  >> Linux

pd:el comando completo es demasiado largo

En Linux, con el ps de procps(-ng) :

ps -fwwp 2755

Sin embargo, en las versiones de Linux anteriores a la 4.2, todavía está limitado (por el kernel (/proc/2755/cmdline ) a 4k) y no puedes obtener más excepto pidiéndole al proceso que te lo diga o usando un depurador.

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

Para imprimir el cuarto argumento con hasta 5000 caracteres:

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

Si desea algo no intrusivo, puede intentar obtener la información de /proc/2755/mem (tenga en cuenta que si el kernel.yama.ptrace_scope no está establecido en 0, necesitará permisos de superusuario para eso). Esto a continuación funciona para mí (imprime todos los argumentos y variables de entorno), pero creo que no hay mucha garantía (el error y el manejo de entrada inesperado se dejan como un ejercicio para el lector):

$ 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

(reemplace "$!" con la identificación del proceso). Lo anterior usa el hecho de que Linux pone las cadenas apuntadas por argv[] , envp[] y el nombre del archivo ejecutado en la parte inferior de la pila del proceso.

Lo anterior busca en esa pila la cadena más baja entre dos conjuntos de dos o más bytes NUL consecutivos. No funciona si alguno de los argumentos o cadenas de env está vacío, porque entonces tendrá una secuencia de 2 bytes NUL en medio de esos argv o envp. Además, no sabemos dónde terminan las cadenas argv y dónde comienzan las envp.

Una solución para eso sería refinar esa heurística mirando hacia atrás para encontrar el contenido real de argv[] (los punteros). Esto a continuación funciona en arquitectura i386 y amd64 para ejecutables ELF al menos:

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

Básicamente, hace lo mismo que arriba, pero una vez que ha encontrado la primera cadena de argv[] (o al menos uno de los argv[] o envp[] cadenas si hay vacíos), conoce su dirección, por lo que mira hacia atrás en el resto superior de la pila en busca de un puntero con el mismo valor. Luego sigue mirando hacia atrás hasta que encuentra un número que no puede ser un indicador de esos, y ese es argc . Entonces el siguiente entero es argv[0] . Y sabiendo argv[0] y argc , puede mostrar la lista de argumentos.

Eso no funciona si el proceso ha escrito en su argv[] posiblemente anulando algunos delimitadores NUL o si argc es 0 (argc generalmente es al menos 1 para incluir argv[0] ) pero debería funcionar en el caso general al menos para los ejecutables ELF.

En 4.2 y posteriores, /proc/<pid>/cmdline ya no está truncado, pero ps en sí tiene un ancho máximo de visualización de 128K.


Añade uno o dos -w banderas Hace que la salida sea más ancha. p.ej. ps auxww .


En Linux kernel 4.2 y posteriores, /proc/<pid>/cmdline ya no está truncado y lo siguiente funciona bien:

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

Linux
  1. ¿Por qué un largo retraso después de que no se encuentra el comando?

  2. Ubuntu – ¿Lista de argumentos demasiado larga?

  3. Comando IP de Linux

  4. Comando cd de linux

  5. No se pueden eliminar archivos del directorio con el error "Lista de argumentos demasiado larga"

Comando W en Linux

Al mando en Linux

comando linux mv

Linux du comando

Comando ifconfig

Linux top -c para mostrar el comando completo