วิธีการรับบรรทัดคำสั่ง args ส่งผ่านไปยังกระบวนการทำงานบนระบบ unix / linux?


202

บน SunOS มีpargsคำสั่งที่พิมพ์อาร์กิวเมนต์บรรทัดคำสั่งที่ส่งไปยังกระบวนการทำงาน

มีคำสั่งที่คล้ายกันในสภาพแวดล้อม Unix อื่น ๆ หรือไม่?


4
tr \\0 ' ' < /proc/<pid>/cmdline
Dmitry Grigoryev

คำตอบ:


307

มีหลายตัวเลือก:

ps -fp <pid>
cat /proc/<pid>/cmdline | sed -e "s/\x00/ /g"; echo

มีข้อมูลเพิ่มเติมใน/proc/<pid>Linux เพียงแค่ดู

สิ่งอื่น ๆ ที่ Unixes อาจแตกต่างกัน psคำสั่งจะทำงานได้ทุกที่ที่/procสิ่งที่เป็นระบบปฏิบัติการที่เฉพาะเจาะจง ยกตัวอย่างเช่นบน AIX ไม่มีในcmdline/proc


49
บน linux คุณอาจต้องใช้ -ww (เช่นps -ww -fp <pid>) เพื่อระบุเอาต์พุตแบบกว้างเนื่องจากหากมีคำสั่งหลายคำสั่งก็จะถูกตัดออก
Silfheed

2
-wwตัวเลือกที่ช่วยให้สามารถเข้าถึงอาร์กิวเมนต์บรรทัดคำสั่งเต็มรูปแบบ (เท่าที่จะถูกเก็บไว้โดย kernel) ดูเพิ่มเติม: วิธี Solaris และ BSD รับพารามิเตอร์ commandline untruncated สำหรับกระบวนการและPS ตัวเลือก
GuruM

3
cat /proc/<pid>/cmdlineใช้ได้กับ Cygwin โดยที่อาร์กิวเมนต์บรรทัด cmd ไม่แสดงpsพร้อมกับตัวเลือกใด ๆ
lechup

3
บน Linux หากคุณต้องการรับargsเท่านั้นคำสั่งคือps -o args -p <pid>และจะพิมพ์argsหรือใช้ -o cmdหากคุณต้องการดูcmdเท่านั้น การพยายามอ่าน/proc/<pid>/cmdlineจะไม่สามารถใช้ได้กับผู้ใช้ที่ด้อยโอกาสเสมอไป psยูทิลิตี้จะทำงาน
alvits

2
คำแนะนำ: ความยาว/proc/<pid>/cmdlineถูก จำกัด (ฮาร์ดโค้ดเป็นค่าของพารามิเตอร์เคอร์เนล PAGE_SIZE) ดังนั้นบรรทัดคำสั่งที่ยาวกว่าจะยังคงถูกตัดทอน! ดูstackoverflow.com/questions/199130/…สำหรับข้อมูลเพิ่มเติม คุณสามารถสอบถามการตั้งค่าเคอร์เนลของคุณด้วยgetconf PAGE_SIZEโดยปกติแล้วคือ 4096
t0r0X

61

นี่จะเป็นการหลอกลวง:

xargs -0 < /proc/<pid>/cmdline

หากไม่มี xargs จะไม่มีช่องว่างระหว่างอาร์กิวเมนต์เนื่องจากถูกแปลงเป็น NUL


3
สิ่งนี้สามารถย่อให้เล็กลงxargs -0 < /proc/<pid>/cmdlineได้
slm

มันจะตัดทอนผลลัพธ์ของฉัน มีคำแนะนำอะไรบ้าง?
johnsam

ไม่เคยสังเกตเห็นการถูกตัดทอน - คุณยกตัวอย่างได้ไหม?
Michael Böckling

ด้วยวิธีนี้คุณไม่สามารถพูดได้ว่าเป็นพื้นที่แบบอินไลน์หรือขอบเขตการโต้แย้ง
ivan_pozdeev

19

commandline เต็ม

สำหรับระบบ Linux & Unix คุณสามารถใช้ps -ef | grep process_nameเพื่อรับบรรทัดคำสั่งแบบเต็ม

บนระบบ SunOS หากคุณต้องการรับบรรทัดคำสั่งแบบเต็มคุณสามารถใช้

/usr/ucb/ps -auxww | grep -i process_name

ในการรับบรรทัดคำสั่งแบบเต็มคุณจะต้องเป็นผู้ใช้ขั้นสูง

รายการข้อโต้แย้ง

pargs -a PROCESS_ID

จะให้รายละเอียดข้อโต้แย้งที่ส่งผ่านไปยังกระบวนการ มันจะส่งออกอาเรย์ของการขัดแย้งในลักษณะนี้:

argv[o]: first argument
argv[1]: second..
argv[*]: and so on..

ฉันไม่พบคำสั่งที่คล้ายกันสำหรับ Linux แต่ฉันจะใช้คำสั่งต่อไปนี้เพื่อให้ได้ผลลัพธ์ที่คล้ายกัน:

tr '\0' '\n' < /proc/<pid>/environ

14

บนLinux

cat /proc/<pid>/cmdline

รับคือคุณ commandline ของกระบวนการ (รวมถึง args) แต่ด้วย whitespaces ทั้งหมดเปลี่ยนเป็นอักขระ NUL


3
ช่องว่างไม่ถูกลบมันถูกแทนที่ด้วย NUL
bdonlan

@bdonlan อาฉันไม่ได้ตรวจสอบว่า จับดี!
lothar

4
xargs -0 echo </ proc / <pid> / cmdline คุณยังสามารถทำได้ด้วย / proc / <pid> / environ เช่นกันแม้ว่าคุณอาจต้องการเพิ่ม -n 1 สำหรับสิ่งนั้น
camh

ในระบบของฉันไม่มีระบบแฟ้ม proc / :( วิธีการแก้ปัญหาอื่น ๆ ?
Hemant

Mine เป็นกระบวนการ java ที่มีพารามิเตอร์ยาวยาว มันจะตัดทอนผลลัพธ์ของฉัน มีคำแนะนำอะไรบ้าง?
johnsam

14

คุณสามารถใช้pgrepกับ-f(บรรทัดคำสั่งเต็ม) และ-l(คำอธิบายแบบยาว):

pgrep -l -f PatternOfProcess

วิธีนี้มีความแตกต่างที่สำคัญกับการตอบสนองอื่น ๆ : มันทำงานบนCygWinดังนั้นคุณสามารถใช้มันเพื่อรับบรรทัดคำสั่งทั้งหมดของกระบวนการใด ๆ ที่ทำงานภายใต้ Windows (ดำเนินการในระดับที่สูงขึ้นหากคุณต้องการข้อมูลเกี่ยวกับกระบวนการยกระดับ / ผู้ดูแลระบบ) . วิธีอื่นใดสำหรับการทำเช่นนี้บน Windows นั้นน่าอึดอัดใจมากกว่า ( ตัวอย่าง )
นอกจากนี้ในการทดสอบของฉันวิธี pgrep ได้รับเพียงระบบเดียวที่ทำงานเพื่อให้ได้เส้นทางที่เต็มรูปแบบสำหรับสคริปต์การทำงานภายในของงูหลาม Cygwin


อันนี้จริง ๆ แล้วพิมพ์ชื่อปฏิบัติการดั้งเดิมได้ด้วย:$ exec -a fakename bash & [1] 14102 [1]+ Stopped exec -a fakename bash $ xargs -0 < /proc/14102/cmdline; fakename $ pgrep -l -f fakename; 14102 bash
อันแฮมเมอร์

ไม่ทำงานสำหรับฉันโดยใช้และpgrep from procps-ng 3.3.15 3.3.12เพียงพิมพ์ชื่อ pid และ prorgam โดยไม่มีข้อโต้แย้ง
Socowi

4

ตัวแปรอื่นของการพิมพ์/proc/PID/cmdlineพร้อมช่องว่างใน Linux คือ:

cat -v /proc/PID/cmdline | sed 's/\^@/\ /g' && echo

ด้วยวิธีนี้catพิมพ์อักขระ NULLเป็น^@และจากนั้นคุณแทนที่ด้วยช่องว่างโดยใช้sed; echoพิมพ์บรรทัดใหม่


FYI คุณสามารถใช้cat -v / proc / PID / cmdline | sed 's / \ ^ @ / \ n / g' สิ่งนี้จะแทนที่อักขระ null ด้วยอักขระขึ้นบรรทัดใหม่ ในการทำเช่นนั้นแต่ละอาร์กิวเมนต์จะถูกพิมพ์ไปยังบรรทัดของมันเอง ด้วยวิธีนี้ง่ายกว่าที่จะบอกข้อโต้แย้งจากอีกข้อหนึ่ง
TSJNachos117


2

แทนที่จะใช้คำสั่งหลายคำสั่งเพื่อแก้ไขกระแสข้อมูลเพียงใช้คำสั่งหนึ่ง - tr แปลอักขระหนึ่งตัวเป็นอีกตัวหนึ่ง:

tr '\0' ' ' </proc/<pid>/cmdline

1

นอกจากวิธีข้างต้นทั้งหมดในการแปลงข้อความหากคุณใช้ 'strings' มันจะสร้างผลลัพธ์เป็นบรรทัดแยกตามค่าเริ่มต้น ด้วยสิทธิประโยชน์เพิ่มเติมที่อาจป้องกันไม่ให้ตัวอักษรใด ๆ ที่อาจเบียดเทอร์มินัลของคุณไม่ให้ปรากฏ

เอาต์พุตทั้งสองในหนึ่งคำสั่ง:

strings / proc // cmdline / proc // environ

คำถามจริงคือ ... มีวิธีดูบรรทัดคำสั่งจริงของกระบวนการใน Linux ที่มีการเปลี่ยนแปลงเพื่อให้ cmdline มีข้อความที่เปลี่ยนแปลงแทนคำสั่งจริงที่ถูกเรียกใช้


1

บนโซลาริส

     ps -eo pid,comm

คล้ายกันสามารถใช้กับระบบยูนิกซ์เช่น


1

บน Linux ด้วย bash เพื่อส่งออกเป็น args ที่ยกมาเพื่อให้คุณสามารถแก้ไขคำสั่งและรันซ้ำได้

</proc/"${pid}"/cmdline xargs --no-run-if-empty -0 -n1 \
    bash -c 'printf "%q " "${1}"' /dev/null; echo

บน Solaris ด้วย bash (ทดสอบด้วย 3.2.51 (1) - ปล่อย) และไม่มี gnu userland:

IFS=$'\002' tmpargs=( $( pargs "${pid}" \
    | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
    | tr '\n' '\002' ) )
for tmparg in "${tmpargs[@]}"; do
    printf "%q " "$( echo -e "${tmparg}" )"
done; echo

ตัวอย่าง bash Linux (วางใน terminal):

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &

## recover into eval string that assigns it to argv_recovered
eval_me=$(
    printf "argv_recovered=( "
    </proc/"${!}"/cmdline xargs --no-run-if-empty -0 -n1 \
        bash -c 'printf "%q " "${1}"' /dev/null
    printf " )\n"
)

## do eval
eval "${eval_me}"

## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

เอาท์พุท:

MATCH

ตัวอย่าง Solaris Bash:

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &
pargs "${!}"
ps -fp "${!}"

declare -p tmpargs
eval_me=$(
    printf "argv_recovered=( "
    IFS=$'\002' tmpargs=( $( pargs "${!}" \
        | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
        | tr '\n' '\002' ) )
    for tmparg in "${tmpargs[@]}"; do
        printf "%q " "$( echo -e "${tmparg}" )"
    done; echo
    printf " )\n"
)

## do eval
eval "${eval_me}"


## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

เอาท์พุท:

MATCH

0

หากคุณต้องการใช้งานได้นานที่สุด (ไม่แน่ใจว่ามีขีด จำกัด ) ใกล้เคียงกับ Solaris pargs ของคุณสามารถใช้สิ่งนี้บน Linux & OSX:

ps -ww -o pid,command [-p <pid> ... ]

-1

ลอง ps -nใน terminal linux สิ่งนี้จะแสดง:

1. กระบวนการทั้งหมดรันบรรทัดคำสั่งและPIDของพวกเขา

  1. โปรแกรมเน้นกระบวนการ

หลังจากนั้นคุณจะรู้ว่ากระบวนการใดที่จะฆ่า

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