เอาต์พุต ps พร้อมกับรูปแบบวันที่ iso?


9

ฉันต้องการเรียงลำดับผลลัพธ์ตามlstart(เริ่มต้นกระบวนการ):

ps -eo lstart,pid,cmd 

มีวิธีส่งออก lstart ในรูปแบบ ISO เช่น YYYY-MM-DD HH: MM: SS หรือไม่

แต่การเรียงลำดับเพียงอย่างเดียวไม่สามารถแก้ไขได้ ฉันต้องการรูปแบบวันที่ ISO จริง ๆ


เหตุใดจึงlstartมีรูปแบบที่แปลกประหลาด มันใกล้กับ RFC 2822 แต่เมื่อเทียบกับปีที่แล้ว
vaughan

คำตอบ:


10

มีวิธีการส่งออกlstartในรูปแบบ ISO YYYY-MM-DD HH:MM:SSหรือไม่

ด้วยawk+ dateความร่วมมือ:

ps -eo lstart,pid,cmd --sort=start_time | awk '{ 
       cmd="date -d\""$1 FS $2 FS $3 FS $4 FS $5"\" +\047%Y-%m-%d %H:%M:%S\047"; 
       cmd | getline d; close(cmd); $1=$2=$3=$4=$5=""; printf "%s\n",d$0 }'

แนวทางอื่น ๆ โดยใช้คำหลักps etimes (เวลาที่ผ่านไปนับตั้งแต่กระบวนการเริ่มต้นเป็นวินาที):

ps -eo etimes,pid,cmd --sort=etimes | awk '{ 
       cmd="date -d -"$1"seconds +\047%Y-%m-%d %H:%M:%S\047"; 
       cmd | getline d; close(cmd); $1=""; printf "%s\n",d$0 }' 
  • date -d -"$1"seconds- ความแตกต่างระหว่างการประทับเวลาปัจจุบันและelapsedเวลาจะให้ค่าการประทับเวลาของกระบวนการ

2
ไม่มีวิธีที่ง่ายกว่านี้ไหม?
guettli

3
หากคุณใช้รูปแบบ PS etimesแทนคุณจะได้รับเวลาที่ผ่านไปในไม่กี่วินาทีซึ่งเป็นบิตง่ายที่จะผ่านเข้าไปในlstart date -d -999seconds
2560

@ meuh ใช่ว่าจะสั้นลงเล็กน้อยฉันได้ทำการอัปเดตแล้ว
RomanPerekhrest

@guettli ไม่สามารถเรียกได้ง่ายขึ้น แต่คุณมีวิธีที่สั้นกว่าเล็กน้อย
RomanPerekhrest

4

คุณสามารถจัดเรียงด้วย:

ps -eo lstart,pid,cmd --sort=start_time

ขอบคุณฉันขยายคำถามของฉัน ฉันต้องการรูปแบบวันที่ของ iso ด้วย
guettli

2

โปรดทราบว่าlstartไม่ใช่หนึ่งในpsคอลัมน์Unix มาตรฐาน

ไม่ใช่ทุกระบบที่มีหนึ่งและเอาท์พุทที่แตกต่างกันระหว่างการใช้งานและอาจเกิดขึ้นระหว่างสถานที่

ตัวอย่างเช่นบน FreeBSD หรือpsจากprocps-ng(ตามปกติจะพบได้บนระบบที่ไม่ได้ใช้ระบบ Linux) และCโลแคลคุณจะได้รับ:

Wed Nov  1 12:36:15 2017

ใน macOS:

Wed  1 Nov 12:36:15 2017

นอกจากนี้เนื่องจากมันไม่ให้ออฟเซ็ต GMT คุณจึงมีความคลุมเครือในเขตเวลาที่ใช้ DST (ซึ่งมีหนึ่งชั่วโมงในระหว่างปีที่มีวันที่เดียวกันเกิดขึ้นสองครั้ง) และไม่เรียงลำดับตามลำดับเวลาเสมอ

ที่นี่คุณสามารถบังคับเท่าที่จะเป็น UTC และใช้perlของDate::Manipโมดูลที่จะแยกวันในลักษณะที่มีความเข้าใจในรูปแบบธรรมชาติที่แตกต่างกัน:

(export TZ=UTC0 LC_ALL=C
  ps -A -o lstart= -o pid= -o args= |
    perl -MDate::Manip -lpe '
      s/^(\s*\S+){5}/UnixDate(ParseDate($&), "%Y-%m-%dT%T+00:00")/e' |
    sort
)

หรือksh93รูปแบบวันที่ที่ยอมรับด้วย:

(export TZ=UTC0 LC_ALL=C
  unset -v IFS
  ps -A -o lstart= -o pid= -o args= |
    while read -r a b c d e rest; do
      printf '%(%FT%T+00:00)T %s\n' "$a $b $c $d $e" "$rest"
    done
)

(ระวังว่าจะตัดช่องว่างต่อท้ายจากแต่ละบรรทัด)

หรือด้วยzshและ GNU date:

(export LC_ALL=C TZ=UTC0
  (){
    paste -d '\0' <(cut -c1-24 < $1 | date -f- --iso-8601=s) \
                  <(cut -c25-  < $1) | sort
  } =(ps -A -o lstart= -o pid= -o args=)
)

หรือด้วยbash(หรือzsh) บน Linux เท่านั้นและด้วย GNU date:

(export LC_ALL=C TZ=UTC0
  {
    paste -d '\0' <(cut -c1-24 | date -f- --iso-8601=s) \
                  <(cut -c25- < /dev/stdin) | sort
  } <<< "$(ps -A -o lstart= -o pid= -o args=)"
)

นอกจากนี้โปรดระวังว่าเวลาเริ่มต้นกระบวนการไม่จำเป็นต้องเหมือนกับครั้งสุดท้ายที่กระบวนการดำเนินการคำสั่งเนื่องจากกระบวนการโดยทั่วไปสามารถเรียกใช้มากกว่าหนึ่งคำสั่งได้ตลอดอายุการใช้งาน . กล่าวอีกนัยหนึ่งมันไม่จำเป็นต้องสอดคล้องกับเวลาที่คำสั่ง ( argsฟิลด์มาตรฐานเทียบเท่าcmd) เริ่มต้นขึ้น

$ sh -c 'sleep 4; exec sleep 123' & sleep 234 & sleep 5
[1] 9380
[2] 9381(export TZ=UTC0 LC_ALL=C; ps -o lstart,pid,args | perl -MDate::Manip -lpe 's/^(\s*\S+){5}/UnixDate(ParseDate($&), "%Y-%m-%dT%T+00:00")/e')

2017-10-30T17:21:06+00:00  3071 zsh
2017-11-01T15:47:48+00:00  9380 sleep 123
2017-11-01T15:47:48+00:00  9381 sleep 234

ดูว่าsleep 123มีการเริ่มต้นอย่างไรในเวลาเดียวกันsleep 234แม้ว่าจะเริ่มขึ้น 4 วินาทีในภายหลัง นั่นเป็นเพราะกระบวนการ 9388 เริ่มต้นทำงานsh(และรอ 4 วินาทีsleep 4) ก่อนที่จะดำเนินการsleep 123(และก่อนหน้านั้นมันกำลังรันzshโค้ดเนื่องจากมันถูกใช้งานโดยเชลล์เชิงโต้ตอบของฉันดังนั้นในเวลาที่แตกต่างกันสำหรับกระบวนการนั้นคุณจะต้อง เห็นได้ในpsผลลัพธ์: zshจากshนั้นจากนั้นsleep)


1
ขอบคุณสำหรับคำตอบ. ตอนนี้ฉันมีคำถามมากกว่าเดิม ฉันคิดว่ามีวิธีแก้ปัญหาที่ง่ายและเรียบง่าย
guettli

1

นี่คือการใช้งานที่มีประสิทธิภาพสูงกว่า (ไม่จำเป็นต้องดำเนินการกระบวนการใหม่ต่อบรรทัด):

ps -eo etimes,pid,args --sort=etimes | awk 'BEGIN{now=systime()} {$1=strftime("%Y-%m-%d %H:%M:%S", now-$1); print $0}'

และสิ่งนี้ทำให้เปลี่ยนการเรียงลำดับคอลัมน์ได้ง่ายเช่นกัน ตัวอย่างเช่นpidครั้งแรกและเวลาเริ่มต้นเป็นคอลัมน์ที่สอง:

ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.