Câu trả lời:
Có cách nào để xuất ra
lstart
ở định dạng ISO như thếYYYY-MM-DD HH:MM:SS
nà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à elapsed
thời gian, sẽ đưa ra giá trị dấu thời gian của quy trìnhetimes
thay vì lstart
bạ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
.
Bạn có thể sắp xếp với:
ps -eo lstart,pid,cmd --sort=start_time
Lưu ý rằng đó lstart
không phải là một trong các ps
cộ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 ps
từ procps-ng
(như thường thấy trên các hệ thống không dựa trên Linux) và C
ngô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 perl
của Date::Manip
module để 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 ksh93
cũ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 zsh
và 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 ( args
trườ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 234
mặ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 zsh
mã 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
).
Đâ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}'
lstart
có một định dạng wierd như vậy. Nó gần với RFC 2822 nhưng cuối năm.