ISO日付形式のps出力?


9

この出力をlstart(プロセスの開始)で並べ替えたい:

ps -eo lstart,pid,cmd 

lstartをYYYY-MM-DD HH:MM:SSのようなISO形式で出力する方法はありますか?

しかし、並べ替えだけでは解決しません。ISO日付形式にしたいのですが。


なぜlstartそのような奇妙なフォーマットがあるのですか?これはRFC 2822に近いですが、最後は年です。
ヴォーン

回答:


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 2017年

3
etimes代わりにps形式を使用lstartすると、経過時間を秒単位で取得できますdate -d -999seconds。これは、に渡すのが少し簡単です。
meuh

@meuh、はい、少し短くなります。更新しました
RomanPerekhrest

@guettli、それを簡単に呼び出すことはできませんが、少し短い方法があります
RomanPerekhrest


2

これlstartは、標準のUnix psカラムの1つではありません。

すべてのシステムに1つあるわけではなく、出力は実装間で、場合によってはロケール間で異なります。

たとえば、FreeBSDまたはpsfrom procps-ng(通常、非組み込みLinuxベースのシステムで見られる)とCロケールを使用すると、次のようになります。

Wed Nov  1 12:36:15 2017

macOSの場合:

Wed  1 Nov 12:36:15 2017

また、GMTオフセットが提供されないため、DSTを実装するタイムゾーンでは出力が不明確になり(年に1時間あり、同じ日付が2回発生する)、常に時系列で並べ替えられるとは限りません。

ここでは、時刻を強制的に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
)

(各行から末尾の空白を削除することに注意してください)

または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のみ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

4秒後に開始されたのにsleep 123、同時に開始されたように見えることを確認してくださいsleep 234。それは、その9388プロセスが最初に実行される前にsh(そして4秒間待機してからsleep 4)、それが実行される前にsleep 123(そしてその前にzsh、インタラクティブシェルによって分岐されたときにコードを実行していたため、さまざまな時点で、そのプロセスについて、見られるps出力:zsh、そしてsh、それからsleep)。


1
お返事ありがとうございます。今、以前よりも多くの質問があります。簡単でシンプルな解決策があると思いました。
guettli 2017年

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最初の時間と2番目の列としての開始時間:

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.