wyjście ps z formatem daty ISO?

9

Chciałbym posortować te dane wyjściowe według lstart(początek procesu):

ps -eo lstart,pid,cmd 

Czy istnieje sposób na wyjście lstart w formacie ISO, takim jak RRRR-MM-DD GG: MM: SS?

Ale samo sortowanie nie rozwiązuje tego. Naprawdę chciałbym mieć format daty ISO.

guettli
źródło
Dlaczego lstartma tak dziwny format. Jest zbliżony do RFC 2822, ale z końcem roku.
vaughan

Odpowiedzi:

10

Czy istnieje sposób na wyjście lstartw formacie ISO, takim jak YYYY-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 elapsedczasem, poda wartość znacznika czasu procesu
Roman Perekhrest
źródło
2
Czy nie ma prostszego sposobu?
guettli,
3
Jeśli etimeszamiast tego lstartużyjesz formatu ps , otrzymasz upływ czasu w sekundach, który jest nieco łatwiejszy do przejścia date -d -999seconds.
Meuh
@meuh, tak, to byłoby trochę krótsze, zrobiłem aktualizację
RomanPerekhrest
@ guettli, nie można tego nazwać łatwiej, ale masz nieco krótszą drogę
RomanPerekhrest
4

Możesz sortować za pomocą:

ps -eo lstart,pid,cmd --sort=start_time
Ipor Sircer
źródło
Dziękuję, rozszerzyłem moje pytanie. Chcę też formatu daty ISO.
guettli,
2

Zauważ, że lstartnie jest to jedna ze standardowych pskolumn 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 psod procps-ng(jak zwykle znaleźć na non-wbudowane systemy oparte na systemie Linux) oraz na Clokalizacji, 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::Manipmoduł 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 ksh93któ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 zshi 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 ( argspola, 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 123widać, że został uruchomiony w tym samym czasie, sleep 234nawet 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ł zshkod, ponieważ został rozwidlony przez moją interaktywną powłokę, więc w różnych momentach dla tego procesu miałbyś widoczne w danych pswyjściowych: zshwtedy sh, potem sleep).

Stéphane Chazelas
źródło
1
Dziękuję za Twoją odpowiedź. Teraz mam więcej pytań niż wcześniej. Myślałem, że istnieje łatwe i proste rozwiązanie.
guettli,
1

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 pidpierwsza 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}'
Mikko Rantalainen
źródło