đầu ra ps với định dạng ngày iso?


9

Tôi muốn sắp xếp đầu ra này theo lstart(bắt đầu quá trình):

ps -eo lstart,pid,cmd 

Có cách nào để xuất ra lstart ở định dạng ISO như YYYY-MM-DD HH: MM: SS không?

Nhưng phân loại một mình không giải quyết nó. Tôi thực sự muốn có định dạng ngày ISO.


Tại sao lstartcó một định dạng wierd như vậy. Nó gần với RFC 2822 nhưng cuối năm.
vaughan

Câu trả lời:


10

Có cách nào để xuất ra lstartở định dạng ISO như thế YYYY-MM-DD HH:MM:SSnào không?

Với sự hợp tác 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 }'

Cách tiếp cận khác bằng cách sử dụng từ khóa ps etimes (thời gian trôi qua kể từ khi quá trình được bắt đầu, tính bằng giây):

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- sự khác biệt giữa dấu thời gian hiện tại và elapsedthời gian, sẽ đưa ra giá trị dấu thời gian của quy trình

2
Có cách nào dễ dàng hơn không?
guettli

3
Nếu bạn sử dụng định dạng ps etimesthay vì lstartbạn có được thời gian trôi qua tính bằng giây thì việc chuyển vào sẽ dễ dàng hơn một chút date -d -999seconds.
meuh

@meuh, vâng, nó sẽ ngắn hơn một chút, tôi đã thực hiện cập nhật
RomanPerekhrest

@guettli, không thể gọi nó dễ dàng hơn, nhưng bạn có cách ngắn hơn một chút
RomanPerekhrest

4

Bạn có thể sắp xếp với:

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

Cảm ơn bạn, tôi mở rộng câu hỏi của tôi. Tôi muốn định dạng ngày iso, quá.
guettli

2

Lưu ý rằng đó lstartkhông phải là một trong các pscột Unix tiêu chuẩn .

Không phải tất cả các hệ thống đều có một, và đầu ra khác nhau giữa các lần triển khai và có khả năng giữa các địa phương.

Chẳng hạn, trên FreeBSD hoặc với pstừ procps-ng(như thường thấy trên các hệ thống không dựa trên Linux) và Cngôn ngữ, bạn sẽ nhận được:

Wed Nov  1 12:36:15 2017

Trên macOS:

Wed  1 Nov 12:36:15 2017

Ngoài ra, vì nó không cung cấp cho bạn phần bù GMT, đầu ra không rõ ràng trong các múi giờ thực hiện DST (trong đó có một giờ trong năm khi cùng một ngày xảy ra hai lần) và không phải lúc nào cũng sắp xếp theo thứ tự thời gian.

Ở đây, bạn có thể buộc các lần được tính theo giờ UTC và sử dụng perlcủa Date::Manipmodule để phân tích ngày theo một cách mà hiểu định dạng tự nhiên khác nhau:

(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
)

Hoặc ksh93cũng nhận ra các định dạng ngày đó:

(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
)

(hãy cẩn thận với dải khoảng trống từ mỗi dòng)

Hoặc với zshvà 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=)
)

Hoặc chỉ với bash(hoặc zsh) trên Linux và với 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=)"
)

Ngoài ra, hãy lưu ý rằng thời gian bắt đầu quá trình không nhất thiết giống như lần trước khi quy trình thực thi lệnh vì các quy trình thường có thể chạy nhiều hơn một lệnh trong đời (những lệnh này thường không thực hiện lệnh) . Nói cách khác, nó không nhất thiết phải tương ứng với thời gian lệnh ( argstrường, tương đương tiêu chuẩn cmd) được bắt đầu.

$ 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

Xem làm thế nào sleep 123được xem là đã được bắt đầu cùng một lúc sleep 234mặc dù nó đã được bắt đầu 4 giây sau đó. Đó là bởi vì quy trình 9388 ban đầu đã chạy sh(và chờ 4 giây sleep 4) trước khi nó được thực thi sleep 123(và trước đó, nó đang chạy zshmã khi được rẽ nhánh bởi lớp vỏ tương tác của tôi, vì vậy tại các thời điểm khác nhau, trong quá trình đó, bạn sẽ có thấy trong psđầu ra : zsh, sau đó sh, sau đó sleep).


1
Cảm ơn bạn vì câu trả lời. Bây giờ tôi có nhiều câu hỏi hơn trước. Tôi nghĩ rằng có một giải pháp dễ dàng và đơn giản.
guettli

1

Đây là một triển khai với hiệu suất cao hơn (không cần thực hiện quy trình mới trên mỗi dòng):

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

và điều này cũng cho phép thay đổi thứ tự cột khá dễ dàng. Ví dụ pidđầu tiên và thời gian bắt đầu như cột thứ hai:

ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
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.