web-dev-qa-db-ja.com

iso日付形式のps出力?

この出力をlstart(プロセスの開始)で並べ替えます。

ps -eo lstart,pid,cmd 

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

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

9
guettli

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

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 }'

psetimesキーワードを使用した代替アプローチ(プロセスが開始されてからの経過時間、秒単位):

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時間の差により、プロセスのtimestamp値が得られます
10
RomanPerekhrest

次のように並べ替えることができます:

ps -eo lstart,pid,cmd --sort=start_time
4
Ipor Sircer

lstartは標準のUnix ps列の1つではないことに注意してください。

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

たとえば、FreeBSDの場合、またはprocps-ngps(通常は組み込みでないLinuxベースのシステムにあります)とCロケールを使用すると、次のようになります。

Wed Nov  1 12:36:15 2017

MacOSの場合:

Wed  1 Nov 12:36:15 2017

また、GMTオフセットが提供されないため、DSTを実装するタイムゾーン(1年の間に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

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

2

パフォーマンスの高い実装を次に示します(行ごとに新しいプロセスを実行する必要はありません)。

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}'
1