ps 输出为 iso 日期格式?

ps 输出为 iso 日期格式?

我想按lstart(进程开始)对输出进行排序:

ps -eo lstart,pid,cmd 

有没有办法以 ISO 格式输出 lstart,如 YYYY-MM-DD HH:MM:SS?

但仅靠排序并不能解决问题。我真的很想要 ISO 日期格式。

答案1

有没有办法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 }'

替代方法使用附注 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

您可以通过以下方式排序:

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

答案3

请注意,这lstart不是标准 Unix 列之一ps

并非所有系统都有一个输出,并且输出因实现而异,并且可能因语言环境而异。

例如,在 FreeBSD 上或使用psfrom procps-ng(通常在非嵌入式 Linux 系统上找到)和C语言环境,您将获得:

Wed Nov  1 12:36:15 2017

在 macOS 上:

Wed  1 Nov 12:36:15 2017

此外,由于它不提供 GMT 偏移量,因此在实施 DST 的时区(一年中有一个小时相同的日期出现两次)中的输出不明确,并且并不总是按时间顺序排序。

在这里,您可以强制时间为 UTC 并使用perlDate::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
)

(注意它会从每行中删除尾随空白)

或者与zshGNU一起使用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 上使用bash(或zsh) 以及使用 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 秒) (在此之前,它正在运行由我的交互式 shell 分叉的代码,因此在不同的时间点,对于该进程,您将拥有在输出中看到:, then , then )。sleep 4sleep 123zshpszshshsleep

答案4

其他答案似乎已经过时了。只需通过选项即可--date-format '%Y-%m-%dT%H:%M:%S'

procps-ng这在(Linux 标准)的最新版本中可用。

相关内容