Answers:
有没有办法以
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
时间之间的差,将给出进程的时间戳值etimes
而不是ps ,lstart
则需要经过的时间(以秒为单位),这更容易传递给date -d -999seconds
。
请注意,这lstart
不是标准Unix ps
列之一。
并非所有系统都有一个,并且输出在实现之间以及在区域之间可能有所不同。
例如,在FreeBSD上或使用ps
from 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
)
(请注意,它会删除每行的尾随空白)
或with 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=)
)
或仅在(Linux上)和GNU上使用bash
(或zsh
)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
即使在4秒钟后sleep 123
启动,也可以看到如何同时sleep 234
启动。那是因为9388进程最初在执行之前sh
(正在等待4秒钟sleep 4
)正在运行(在此sleep 123
之前,它正在运行zsh
由我的交互式shell分叉的代码,因此在该进程的不同时间点,您将拥有在ps
输出中看到:zsh
,然后是sh
,然后是sleep
)。
这是一个性能更高的实现(不需要每行执行一个新的过程):
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}'
lstart
会有这种奇怪的格式。它接近RFC 2822,但最后一年。