回答:
の
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
。これは、に渡すのが少し簡単です。
次のように並べ替えることができます:
ps -eo lstart,pid,cmd --sort=start_time
これlstart
は、標準のUnix ps
カラムの1つではありません。
すべてのシステムに1つあるわけではなく、出力は実装間で、場合によってはロケール間で異なります。
たとえば、FreeBSDまたはps
from procps-ng
(通常、非組み込みLinuxベースのシステムで見られる)とC
ロケールを使用すると、次のようになります。
Wed Nov 1 12:36:15 2017
macOSの場合:
Wed 1 Nov 12:36:15 2017
また、GMTオフセットが提供されないため、DSTを実装するタイムゾーンでは出力が不明確になり(年に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
4秒後に開始されたのにsleep 123
、同時に開始されたように見えることを確認してくださいsleep 234
。それは、その9388プロセスが最初に実行される前にsh
(そして4秒間待機してからsleep 4
)、それが実行される前にsleep 123
(そしてその前に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}'
lstart
そのような奇妙なフォーマットがあるのですか?これはRFC 2822に近いですが、最後は年です。