この出力をlstart
(プロセスの開始)で並べ替えます。
ps -eo lstart,pid,cmd
LstartをYYYY-MM-DD HH:MM:SSのようなISO形式で出力する方法はありますか?
しかし、並べ替えだけでは解決しません。 ISO日付形式にしたいのですが。
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値が得られます次のように並べ替えることができます:
ps -eo lstart,pid,cmd --sort=start_time
lstart
は標準のUnix ps
列の1つではないことに注意してください。
すべてのシステムに1つあるわけではなく、出力は実装間で、場合によってはロケール間で異なります。
たとえば、FreeBSDの場合、またはprocps-ng
のps
(通常は組み込みでないLinuxベースのシステムにあります)とC
ロケールを使用すると、次のようになります。
Wed Nov 1 12:36:15 2017
MacOSの場合:
Wed 1 Nov 12:36:15 2017
また、GMTオフセットが提供されないため、DSTを実装するタイムゾーン(1年の間に1日が同じ日付が2回発生する)での出力はあいまいであり、常に時系列で並べ替えられるとは限りません。
ここでは、時刻を強制的に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
)
(各行から末尾の空白を削除することに注意してください)
または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
)。
パフォーマンスの高い実装を次に示します(行ごとに新しいプロセスを実行する必要はありません)。
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}'