ps: คำสั่งแบบเต็มยาวเกินไป


26

ขอให้เป็นวันที่ดี!

ฉันใช้ 'ps' เพื่อดูคำสั่งที่เริ่มต้นกระบวนการ ปัญหาคือคำสั่งนั้นยาวเกินไปและ 'ps' ไม่แสดงอย่างสมบูรณ์

ตัวอย่าง: ฉันใช้คำสั่ง 'ps -p 2755 | น้อยกว่าและมีผลลัพธ์ต่อไปนี้

  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.

ดังนั้นบรรทัดคำสั่งยาวเกินไปและคำสั่งหยุดกลางวลี ฉันจะเห็นมันทั้งหมดได้อย่างไร?

คำตอบ:


38

บน Linux ด้วยpsจากprocps(-ng):

ps -fwwp 2755

ในรุ่น Linux ก่อนหน้า 4.2 จะยังคงมีข้อ จำกัด (โดยเคอร์เนล ( /proc/2755/cmdline) ถึง 4k) และคุณไม่สามารถรับเพิ่มเติมได้โดยขอให้กระบวนการบอกให้คุณทราบหรือใช้ดีบักเกอร์

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

หากต้องการพิมพ์ arg ที่ 4 ที่มีอักขระสูงสุด 5,000 ตัว:

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

หากคุณต้องการสิ่งที่ไม่ล่วงล้ำคุณสามารถลองและรับข้อมูลจาก/proc/2755/mem(โปรดทราบว่าหากkernel.yama.ptrace_scopeไม่ได้ตั้งค่าเป็น 0 คุณจะต้องมีสิทธิ์ superuser สำหรับสิ่งนั้น) ด้านล่างนี้ใช้งานได้สำหรับฉัน (พิมพ์อาร์กิวเมนต์และตัวแปรสภาพแวดล้อมทั้งหมด) แต่ไม่มีอะไรรับประกันได้มากนักที่ฉันจะคิดว่า (ข้อผิดพลาดและการจัดการอินพุตที่ไม่คาดคิดถูกทิ้งไว้เป็นแบบฝึกหัดต่อผู้อ่าน):

$ 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

(แทนที่"$!"ด้วย id กระบวนการ) การใช้งานที่เหนือความจริงที่ว่าลินุกซ์ทำให้สตริงชี้ไปตามargv[], envp[]และชื่อไฟล์ดำเนินการที่ด้านล่างของสแต็คของกระบวนการที่

ด้านบนจะดูในสแต็กนั้นสำหรับสตริงที่อยู่ด้านล่างสุดระหว่างสองชุดของ NUL สองไบต์หรือมากกว่าติดต่อกัน ไม่ทำงานหากมีข้อโต้แย้งหรือสตริง env ว่างเพราะคุณจะมีลำดับ 2 NUL ไบต์อยู่ตรงกลางของ argv หรือ envp นอกจากนี้เรายังไม่รู้ว่าที่ใดที่สตริง argv หยุดและตำแหน่งที่ envp เริ่มต้น

งานที่ต้องทำคือปรับแต่งฮิวริสติกด้วยการมองย้อนกลับไปที่เนื้อหาที่แท้จริงของargv[](พอยน์เตอร์) ด้านล่างนี้ใช้งานได้กับสถาปัตยกรรม i386 และ amd64 สำหรับ executables ของ 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;' "$!"

โดยทั่วไปแล้วมันจะเหมือนกับข้างบน แต่เมื่อพบสตริงแรกของargv[](หรืออย่างน้อยหนึ่งในargv[]หรือenvp[]ถ้ามี empties) มันจะรู้ที่อยู่ของมันดังนั้นจึงมองย้อนกลับไปในส่วนที่เหลือของสแต็กสำหรับ ตัวชี้ที่มีค่าเดียวกัน argcจากนั้นช่วยให้มองย้อนกลับจนกว่าจะพบตัวเลขที่ไม่สามารถเป็นตัวชี้ไปยังผู้ที่เป็นและที่เป็น argv[0]แล้วจำนวนเต็มต่อไปคือ และการรู้argv[0]และargcมันสามารถแสดงรายการของข้อโต้แย้ง

ไม่สามารถใช้งานได้หากกระบวนการเขียนถึงargv[]ตัวคั่น NUL บางตัวหรือถ้าargcเป็น 0 ( argcโดยทั่วไปจะรวมอย่างน้อย 1 argv[0]) แต่ควรทำงานในกรณีทั่วไปอย่างน้อยสำหรับ executables ของ ELF

ใน 4.2 และใหม่กว่า/proc/<pid>/cmdlineจะไม่ถูกตัดทอนอีกต่อไป แต่psตัวมันเองมีความกว้างหน้าจอสูงสุดที่ 128K


คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับดีบักเกอร์ได้ไหม ฉันจะแนบมันเข้ากับกระบวนการที่กำลังรันอยู่ได้อย่างไร?
V. Artyukhov

1
@ V.Artyukhov ฉันเข้าใจว่าเป็นสิ่งที่-p $!ทำ ( $!เป็น PID ของกระบวนการที่เริ่มต้นล่าสุดซึ่งเนื่องจากมันเป็นพื้นหลังจะยังคงทำงานเมื่อ gdb ถูกเรียก)
CVn

ใช่ต่อสู้กับคำสั่งยาวด้วยคำสั่งที่ยาวขึ้น พูดจากัน +1 สำหรับคำตอบพร้อมคำอธิบายและเอกสารที่ดี
Stan Strum


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.