Odpowiedzi:
Czy istnieje sposób na wyjście
lstart
w formacie ISO, takim jakYYYY-MM-DD HH:MM:SS
?
Przy współpracy 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 }'
Alternatywne podejście przy użyciu słowa kluczowego ps etimes
(czas, który upłynął od rozpoczęcia procesu, w sekundach):
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
- różnica między bieżącym znacznikiem czasu a elapsed
czasem, poda wartość znacznika czasu procesuetimes
zamiast tego lstart
użyjesz formatu ps , otrzymasz upływ czasu w sekundach, który jest nieco łatwiejszy do przejścia date -d -999seconds
.
Możesz sortować za pomocą:
ps -eo lstart,pid,cmd --sort=start_time
Zauważ, że lstart
nie jest to jedna ze standardowych ps
kolumn uniksowych .
Nie wszystkie systemy mają jeden, a wyniki różnią się między implementacjami i potencjalnie między lokalizacjami.
Na przykład, na FreeBSD lub z ps
od procps-ng
(jak zwykle znaleźć na non-wbudowane systemy oparte na systemie Linux) oraz na C
lokalizacji, dostaniesz:
Wed Nov 1 12:36:15 2017
Na macOS:
Wed 1 Nov 12:36:15 2017
Ponadto, ponieważ nie daje to przesunięcia GMT, dane wyjściowe są niejednoznaczne w strefach czasowych, które implementują DST (gdzie jest jedna godzina w ciągu roku, w której te same daty występują dwa razy) i nie zawsze sortują się chronologicznie.
Tutaj można zmusić razy, aby być UTC i używać perl
„s Date::Manip
moduł do analizowania datę w sposób zrozumiały dla różnych formatów naturalne:
(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
)
Lub z ksh93
którymi rozpoznaje również te formaty dat:
(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
)
(uwaga: usuwa ona końcowe spacje z każdej linii)
Lub z zsh
i 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=)
)
Lub z bash
(lub zsh
) tylko w systemie Linux i 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=)"
)
Uważaj również, aby czas rozpoczęcia procesu niekoniecznie był taki sam jak ostatni raz, gdy proces wykonał polecenie, ponieważ procesy mogą generalnie wykonać więcej niż jedno polecenie w ciągu swojego życia (te, które nie są tymi, które nigdy nie wykonują polecenia) . Innymi słowy, niekoniecznie odpowiada to czasowi uruchomienia polecenia ( args
pola, standardowego odpowiednika 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
Zobacz, jak sleep 123
widać, że został uruchomiony w tym samym czasie, sleep 234
nawet jeśli został uruchomiony 4 sekundy później. Dzieje się tak, ponieważ proces 9388 początkowo działał sh
(i czekał 4 sekundy sleep 4
) przed jego wykonaniem sleep 123
(a wcześniej działał zsh
kod, ponieważ został rozwidlony przez moją interaktywną powłokę, więc w różnych momentach dla tego procesu miałbyś widoczne w danych ps
wyjściowych: zsh
wtedy sh
, potem sleep
).
Oto implementacja o wyższej wydajności (nie trzeba wykonywać nowego procesu na linię):
ps -eo etimes,pid,args --sort=etimes | awk 'BEGIN{now=systime()} {$1=strftime("%Y-%m-%d %H:%M:%S", now-$1); print $0}'
i pozwala to również dość łatwo zmieniać kolejność kolumn. Na przykład pid
pierwsza i godzina rozpoczęcia jako druga kolumna:
ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
lstart
ma tak dziwny format. Jest zbliżony do RFC 2822, ale z końcem roku.