วิธีรับบรรทัดคำสั่งทั้งหมดจากกระบวนการ


43

ฉันจะรับอาร์กิวเมนต์คำสั่งหรือบรรทัดคำสั่งทั้งหมดจากกระบวนการที่รันโดยใช้ชื่อกระบวนการได้อย่างไร

ตัวอย่างเช่นกระบวนการนี้:

# ps
PID   USER     TIME   COMMAND
 1452 root       0:00 /sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid

และสิ่งที่ฉันต้องการคือ/sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pidหรือข้อโต้แย้ง ฉันรู้ชื่อกระบวนการและต้องการข้อโต้แย้ง ฉันใช้ Busybox กับ SliTaz


คุณต้องการที่จะประมวลผลเอาท์พุทจากps(ไม่แนะนำ) หรือคุณกำลังมองหาคำสั่งทางเลือกบางอย่างเพื่อpsที่จะให้ผลลัพธ์หรือไม่ ต้องทำอะไรเมื่อpsให้เอาต์พุตหลายบรรทัด? พิมพ์ทั้งหมด / แรก / ครั้งสุดท้ายหรือไม่
Anthon

1
คุณใช้ระบบปฏิบัติการใด
Cyrus

ฉันแก้ไขคำถามของฉัน ฉันรู้ชื่อกระบวนการและต้องการข้อโต้แย้ง ฉันใช้ SliTaz (ลินุกซ์เรียบง่าย) กับ Busybox
Michael

@Michael คุณได้ลองargเหมือนcommandเป็นต่อ @John คำตอบ ?
Pandya

ใช่ แต่วิธีการเขียนไปยังตัวแปร? ฉันคิดว่าสองคำสั่ง: PID = pidof <process name>ps -o pid, args | grep $ PID | tr -s "" | cut -d "" -f 2 แต่ด้วยวิธีนี้ฉันไม่ได้รับ args ในตัวแปรเดียว
Michael

คำตอบ:


54

คุณสามารถใช้-oสวิตช์เพื่อระบุรูปแบบผลลัพธ์ของคุณ:

$ ps -eo args

จากหน้าคน :

คำสั่งที่มีข้อโต้แย้งทั้งหมดเป็นสตริง การแก้ไขข้อโต้แย้งอาจปรากฏขึ้น [ ... ]

คุณสามารถใช้-pสวิตช์เพื่อเลือก PID ที่เฉพาะเจาะจง:

$ ps -p [PID] -o args

pidofอาจใช้เพื่อเปลี่ยนจากชื่อกระบวนการเป็น PID ด้วยเหตุนี้จึงอนุญาตให้ใช้-pชื่อ:

$ ps -p $(pidof dhcpcd) -o args

แน่นอนคุณอาจใช้grepสำหรับสิ่งนี้ (ในกรณีนี้คุณต้องเพิ่ม-eสวิตช์):

$ ps -eo args | grep dhcpcd | head -n -1

GNU ps ยังช่วยให้คุณสามารถลบส่วนหัว (แน่นอนนี่ไม่จำเป็นเมื่อใช้grep):

$ ps -p $(pidof dhcpcd) -o args --no-headers

ในระบบอื่น ๆ คุณสามารถใช้ AWK หรือ sed:

$ ps -p $(pidof dhcpcd) -o args | awk 'NR > 1'
$ ps -p $(pidof dhcpcd) -o args | sed 1d

แก้ไข: หากคุณต้องการจับบรรทัดนี้เป็นตัวแปรเพียงใช้$(...)ตามปกติ:

$ CMDLINE=$(ps -p $(pidof dhcpcd) -o args --no-headers)

หรือด้วยgrep:

$ CMDLINE=$(ps -eo args | grep dhcpcd | head -n -1)

@Michael แทนที่argsด้วยcommand(หรือcmd)
Pandya

@Pandya ทั้งคู่cmdและcommandเป็นชื่อแทนargsนี่อาจไม่จำเป็น
John WH Smith

ฉันไม่มีตัวเลือก -p โดยใช้ Busybox: การใช้งาน: ps [-o COL1, COL2 = HEADER] [-T]
Michael

คุณอาจจะใช้การจับเส้นที่คุณสนใจจริงใน:grep ps -eo args | grep dhcpcd | head -n -1ฉันแก้ไขคำตอบของฉัน
John WH Smith

โอ้นี่ดูดีนะ: ps -o args | grep <ชื่อกระบวนการ> | head -n 1
Michael

12

ลองสิ่งนี้:

(ตัวอย่างเอาต์พุตจาก busybox บน OpenWrt บนเราเตอร์ตัวใดตัวหนึ่งของฉัน)

root@ap8:~# xargs -0 printf '%s\n' </proc/991/cmdline
/usr/sbin/uhttpd
-f
-h
/www
-r
ap8
-x
/cgi-bin
-u
/ubus
-t
60
-T
30
-k
20
-A
1
-n
3
-N
100
-R
-p
0.0.0.0:80
-p
[::]:80

/proc/$PID/cmdlineมีข้อโต้แย้งของกระบวนการ$PIDเช่นสตริง C-ish ทีละตัว แต่ละสตริงสิ้นสุดลงเป็นศูนย์

คำพูด arround อาร์กิวเมนต์หรือตัวเลือกบางอย่างเป็นสิ่งเปลือก คุณต้องดูให้ละเอียดยิ่งขึ้นสำหรับบรรทัดที่แสดงและที่ว่างหรืออักขระอื่น ๆ ที่มีความหมายพิเศษสำหรับเชลล์ คุณจะต้องอ้างถึงตัวละครตัวใดตัวหนึ่งหรืออาร์กิวเมนต์ที่สมบูรณ์เมื่อเข้าร่วมบรรทัดเหล่านี้ไปยังบรรทัดคำสั่งอีกครั้ง


1
tr "\0" " " </proc/991/cmdline
Cyrus

@Cyrus: คุณไม่สามารถแยกแยะ args ที่มีช่องว่างจาก args แยกที่อยู่ติดกันได้ โดยการแทนที่ศูนย์ไบต์ด้วยช่องว่างคุณทำลายข้อมูล
yeti

1
ฉันเห็นด้วยที่จะแทนที่\0ด้วย `` ไม่ดี แต่ฉันคิดว่าtr '\0' '\n' < /proc/$foo/cmdlineง่ายกว่าxargsเล็กน้อย
Patrick

printfทำให้ง่ายต่อการเพิ่มเครื่องหมายคำพูดไปยังเอาต์พุตแทรกช่องว่างแทนบรรทัดใหม่และอื่น ๆ เมื่อคิดที่จะเพิ่มการประมวลผลมากขึ้นการผ่านไปprintfเป็นการเริ่มต้นที่ดี
yeti

12

วิธีที่ # 1 - การใช้ ps

ps -eaf | grep 1234คุณสามารถใช้

ตัวอย่าง

$ ps -eaf | grep 28865
saml     28865  9661  0 03:06 pts/2    00:00:00 bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done
saml     28866 28865  0 03:06 pts/2    00:00:00 sleep 10000

หมายเหตุ: Busybox psไม่ได้รวม-eafสวิตช์ดังที่แสดงไว้ด้านบนจากแบบทั่วไปpsที่รวมอยู่ใน Linuxes ส่วนใหญ่ แต่ Busybox psแสดงสิ่งที่ดูเหมือนว่าจะคล้ายกันมากกับตัวอย่างที่ฉันให้ไว้ คุณสามารถติดตั้ง Busybox บน Linux ส่วนใหญ่แล้วเรียกใช้ดังนี้:

$ busybox ps
  852 root       0:00 /sbin/auditd -n
  855 root       0:01 /sbin/audispd
  857 root       0:00 /usr/sbin/sedispatch
  866 root       0:00 /usr/sbin/alsactl -s -n 19 -c -E ALSA_CONFIG_PATH=/etc/alsa/alsactl.conf --initfile=/lib/alsa/init/00main rdaemon
  867 root       0:00 /usr/libexec/bluetooth/bluetoothd
  869 root       0:01 {firewalld} /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid
  871 root       0:32 /usr/libexec/accounts-daemon
  873 rtkit      0:05 /usr/libexec/rtkit-daemon
  875 root       0:00 /usr/sbin/ModemManager
  876 avahi      0:03 avahi-daemon: running [dufresne.local]
  878 root       0:54 /usr/sbin/irqbalance --foreground
  884 root       0:00 /usr/sbin/smartd -n -q never
  886 avahi      0:00 avahi-daemon: chroot helper
  891 chrony     0:01 /usr/sbin/chronyd
  892 root       0:01 /usr/lib/systemd/systemd-logind
  893 dbus       1:28 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

วิธีที่ # 2 - การใช้ / proc

นอกจากนี้คุณยังสามารถดูcmdlineไฟล์ว่าแต่ละ PID /proc/<pid>มีอยู่ตาม

$ cat /proc/28865/cmdline 
bash-csleep 10000; while [ 1 ];do echo hi;sleep 10;done

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

$ tr '\0' ' ' </proc/28865/cmdline
bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done

อ้างอิง


2

ทำความรู้จักกับ PID เพียงแค่ exec

cat / proc / pid / cmdline

ตัวอย่างเช่นสำหรับ PID = 127

# cat /proc/127/cmdline ; echo ""
/usr/lib/jvm/jdk-8-oracle-x64//bin/java-Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager-Djava.library.path=/usr/lib/jni-javaagent:/jmxtrans-agent-1.2.2.jar=/opt/tomcat/conf/jmxtrans-agent.xml-Dcom.sun.management.jmxremote.port=5000-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false-Djava.endorsed.dirs=/opt/tomcat/endorsed-classpath/opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar-Dcatalina.base=/opt/tomcat-Dcatalina.home=/opt/tomcat-Djava.io.tmpdir=/opt/tomcat/temporg.apache.catalina.startup.Bootstrapstart
#
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.