ps: lệnh đầy đủ quá dài


26

Ngày tốt!

Tôi sử dụng 'ps' để xem lệnh bắt đầu quá trình. Vấn đề là lệnh đó quá dài và 'ps' không hiển thị hoàn toàn.

Ví dụ: Tôi sử dụng lệnh 'ps -p 2755 | ít hơn 'và có đầu ra sau

  PID TTY      STAT   TIME COMMAND
2755 ?        Sl   305:05 /usr/java/jdk1.6.0_37/bin/java -Xms64m -Xmx512m -Dflume.monitoring.type=GANGLIA -Dflume.monitoring.hosts=prod.hostname.ru:8649 -cp /etc/flume-ng/conf/acrs-event:/usr/lib/flume-ng/lib/*:/etc/hadoop/conf:/usr/lib/hadoop/lib/activation-1.1.jar:/usr/lib/hadoop/lib/asm-3.2.jar:/usr/lib/hadoop/lib/avro-1.7.4.jar:/usr/lib/hadoop/lib/commons-beanutils-1.7.0.jar:/usr/lib/hadoop/lib/commons-beanutils-core-1.8.0.jar:/usr/lib/hadoop/lib/commons-cli-1.2.jar:/usr/lib/hadoop/lib/commons-codec-1.4.jar:/usr/lib/hadoop/lib/commons-collections-3.2.1.jar:/usr/lib/hadoop/lib/commons-compress-1.4.1.jar:/usr/lib/hadoop/lib/commons-configuration-1.6.jar:/usr/lib/hadoop/lib/commons-digester-1.8.jar:/usr/lib/hadoop/lib/commons-el-1.0.jar:/usr/lib/hadoop/lib/commons-httpclient-3.1.jar:/usr/lib/hadoop/lib/commons-io-2.1.jar:/usr/lib/hadoop/lib/commons-lang-2.5.jar:/usr/lib/hadoop/lib/commons-logging-1.1.1.jar:/usr/lib/hadoop/lib/commons-math-2.1.jar:/usr/lib/hadoop/lib/commons-net-3.1.jar:/usr/lib/hadoop/lib/guava-11.0.2.jar:/usr/lib/hadoop/lib/jackson-core-asl-1.8.8.jar:/usr/lib/hadoop/lib/jackson-jaxrs-1.8.8.jar:/usr/lib/hadoop/lib/jackson-mapper-asl-1.8.8.jar:/usr/lib/hadoop/lib/jackson-xc-1.8.8.jar:/usr/lib/hadoop/lib/jasper-compiler-5.5.23.jar:/usr/lib/hadoop/lib/jasper-runtime-5.5.23.jar:/usr/lib/hadoop/lib/jaxb-api-2.2.2.jar:/usr/lib/hadoop/lib/jaxb-impl-2.2.3-1.jar:/usr/lib/hadoop/lib/jersey-core-1.8.jar:/usr/lib/hadoop/lib/jersey-json-1.8.jar:/usr/lib/hadoop/lib/jersey-server-1.8.jar:/usr/lib/hadoop/lib/jets3t-0.6.1.jar:/usr/lib/hadoop/lib/jettison-1.1.jar:/usr/lib/hadoop/lib/jetty-6.1.26.cloudera.2.jar:/usr/lib/hadoop/lib/jetty-util-6.1.26.cloudera.2.jar:/usr/lib/hadoop/lib/jline-0.9.94.jar:/usr/lib/hadoop/lib/jsch-0.1.42.jar:/usr/lib/hadoop/lib/jsp-api-2.1.jar:/usr/lib/hadoop/lib/jsr305-1.3.9.jar:/usr/lib/hadoop/lib/junit-4.8.2.jar:/usr/lib/hadoop/lib/kfs-0.3.jar:/usr/lib/hadoop/lib/log4j-1.2.17.jar:/usr/lib/hadoop/lib/mockito-all-1.8.5.jar:/usr/lib/hadoop/lib/native:/usr/lib/hadoop/lib/paranamer-2.3.jar:/usr/lib/hadoop/lib/protobuf-java-2.4.0a.jar:/usr/lib/hadoop/lib/servlet-api-2.5.jar:/usr/lib/hadoop/lib/snappy-java-1.0.4.1.jar:/usr/lib/hadoop/lib/stax-api-1.0.1.jar:/usr/lib/hadoop/lib/xmlenc-0.52.jar:/usr/lib/hadoop/lib/xz-1.0.jar:/usr/lib/hadoop/lib/zookeeper-3.4.5-cdh4.3.0.jar:/usr/lib/hadoop/.//bin:/usr/lib/hadoop/.//cloudera:/usr/lib/hadoop/.//etc:/usr/lib/hadoop/.//hadoop-annotations-2.0.0-cdh4.3.0.jar:/usr/lib/hadoop/.//hadoop-annotations.jar:/usr/lib/hadoop/.//hadoop-auth-2.0.0-cdh4.3.0.jar:/usr/lib/hadoop/.//hadoop-auth.jar:/usr/lib/hadoop/.//hadoop-common-2.0.0-cdh4.3.0.jar:/usr/lib/hadoop/.//hadoop-common-2.0.0-cdh4.3.0-tests.jar:/usr/lib/hadoop/.//hadoop-common.jar:/usr/lib/hadoop/.//lib:/usr/lib/hadoop/.//libexec:/usr/lib/hadoop/.//sbin:/usr/lib/hadoop-hdfs/./:/usr/lib/hadoop-hdfs/lib/asm-3.2.jar:/usr/lib/hadoop-hdfs/lib/commons-cli-1.2.jar:/usr/lib/hadoop-hdfs/lib/commons-codec-1.4.jar:/usr/lib/hadoop-hdfs/lib/commons-daemon-1.0.3.jar:/usr/lib/hadoop-hdfs/lib/commons-el-1.0.jar:/usr/lib/hadoop-hdfs/lib/commons-io-2.1.jar:/usr/lib/hadoop-hdfs/lib/commons-lang-2.5.jar:/usr/lib/hadoop-hdfs/lib/commons-logging-1.1.1.jar:/usr/lib/hadoop-hdfs/lib/guava-11.0.2.jar:/usr/lib/hadoop-hdfs/lib/jackson-core-asl-1.8.8.jar:/usr/lib/hadoop-hdfs/lib/jackson-mapper-asl-1.8.8.jar:/usr/lib/hadoop-hdfs/lib/jasper-runtime-5.5.23.jar:/usr/lib/hadoop-hdfs/lib/jersey-core-1.8.jar:/usr/lib/hadoop-hdfs/lib/jersey-server-1.8.jar:/usr/lib/hadoop-hdfs/lib/jetty-6.1.26.cloudera.2.jar:/usr/lib/hadoop-hdfs/lib/jetty-util-6.1.26.cloudera.2.jar:/usr/lib/hadoop-hdfs/lib/jline-0.9.94.jar:/usr/lib/hadoop-hdfs/lib/jsp-api-2.1.jar:/usr/lib/hadoop-hdfs/lib/jsr305-1.3.9.jar:/usr/lib/hadoop-hdfs/lib/log4j-1.2.17.jar:/usr/lib/hadoop-hdfs/lib/protobuf-java-2.4.0a.jar:/usr/lib/hadoop-hdfs/lib/servlet-api-2.5.jar:/usr/lib/hadoop-hdfs/lib/xmlenc-0.52.jar:/usr/lib/hadoop-hdfs/lib/zookeeper-3.4.5-cdh4.3.0.jar:/usr/lib/hadoop-hdfs/.//bin:/usr/lib/hadoop-hdfs/.//cloudera:/usr/lib/hadoop-hdfs/.//hadoop-hdfs-2.0.0-cdh4.3.0.jar:/usr/lib/hadoop-hdfs/.//hadoop-hdfs-2.0.

Vì vậy, dòng lệnh quá dài và lệnh dừng giữa cụm từ. Làm thế nào tôi có thể nhìn thấy toàn bộ nó?

Câu trả lời:


38

Trên Linux, với pstừ procps(-ng):

ps -fwwp 2755

Trong các phiên bản Linux trước 4.2, nó vẫn bị giới hạn (bởi kernel ( /proc/2755/cmdline) đến 4k) và bạn không thể nhận được nhiều hơn ngoại trừ bằng cách yêu cầu quy trình nói với bạn hoặc sử dụng trình gỡ lỗi.

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

Để in đối số thứ 4 với tối đa 5000 ký tự:

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

Nếu bạn muốn thứ gì đó không xâm phạm, bạn có thể thử và lấy thông tin từ /proc/2755/mem(lưu ý rằng nếu giá trị kernel.yama.ptrace_scopenày không được đặt thành 0, bạn sẽ cần quyền siêu người dùng cho điều đó). Điều này dưới đây hoạt động với tôi (in tất cả các đối số và biến môi trường), nhưng tôi không nghĩ nhiều (tôi sẽ xử lý lỗi và xử lý đầu vào không mong muốn như một bài tập cho người đọc):

$ 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

(thay thế "$!"bằng id quá trình). Việc sử dụng trên thực tế là puts Linux các dây được trỏ đến bởi argv[], envp[]và tên tập tin thực thi ở dưới cùng của ngăn xếp của quá trình.

Ở trên có vẻ như trong ngăn xếp đó cho chuỗi dưới cùng ở giữa hai bộ hai hoặc nhiều byte NUL liên tiếp. Nó không hoạt động nếu bất kỳ đối số hoặc chuỗi env nào trống, bởi vì sau đó bạn sẽ có một chuỗi gồm 2 byte NUL ở giữa các argv hoặc envp. Ngoài ra, chúng tôi không biết chuỗi argv dừng ở đâu và chuỗi envp bắt đầu từ đâu.

Một công việc xung quanh cho điều đó sẽ là để tinh chỉnh heuristic bằng cách nhìn ngược lại nội dung thực tế của argv[](các con trỏ). Điều này dưới đây hoạt động trên kiến ​​trúc i386 và amd64 cho các tệp thực thi ELF ít nhất:

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

Về cơ bản, nó thực hiện tương tự như trên, nhưng một khi nó đã tìm thấy chuỗi đầu tiên của argv[](hoặc ít nhất một trong số argv[]hoặc envp[]chuỗi nếu có trống), nó biết địa chỉ của nó, vì vậy nó nhìn ngược vào phần còn lại trên cùng của ngăn xếp một con trỏ có cùng giá trị đó. Sau đó tiếp tục nhìn về phía sau cho đến khi nó tìm thấy một số không thể là con trỏ đến những số đó, và đó là argc. Sau đó, số nguyên tiếp theo là argv[0]. Và biết argv[0]argc, nó có thể hiển thị danh sách các đối số.

Điều đó không hoạt động nếu quy trình đã được viết cho nó argv[]có thể ghi đè một số dấu phân cách NUL hoặc nếu bằng argc0 ( argcthường là ít nhất 1 để bao gồm argv[0]) nhưng nên hoạt động trong trường hợp chung ít nhất là cho các tệp thực thi ELF.

Trong 4.2 và mới hơn, /proc/<pid>/cmdlinekhông còn bị cắt ngắn nữa, nhưng psbản thân nó có chiều rộng hiển thị tối đa là 128K.


Bạn có thể nói thêm về trình gỡ lỗi không? Làm thế nào tôi có thể gắn nó vào quá trình chạy?
V. Artyukhov

1
@ V.Artyukhov Tôi cho rằng đó là những gì -p $!nó làm ( $!là PID của quá trình bắt đầu gần đây nhất, vì nó được làm nền sẽ vẫn chạy khi gdb được gọi).
một CVn

Vâng, chiến đấu các lệnh dài với các lệnh thậm chí dài hơn. Đùa sang một bên, +1 cho câu trả lời với một lời giải thích và tài liệu tốt.
Stan Strum

12

Thêm một hoặc hai -wcờ. Nó làm cho đầu ra rộng hơn. ví dụ ps auxww.


5

Trong Linux kernel 4.2 trở lên, /proc/<pid>/cmdlinekhông còn bị cắt cụt và các thao tác sau đây hoạt động tốt:

xargs -0 printf '%s\n' < /proc/2755/cmdline
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.