ps вихід з форматом iso date?


9

Я хотів би сортувати цей результат за lstart(початок процесу):

ps -eo lstart,pid,cmd 

Чи є спосіб вивести lstart у форматі ISO типу YYYY-MM-DD HH: MM: SS?

Але сортування одне не вирішує. Я дуже хотів би мати формат дати ISO.


Чому lstartтакий формат wierd. Він близький до RFC 2822, але з кінцем року.
воган

Відповіді:


10

Чи є спосіб вивести такий 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часом, дасть значення часової позначки процесу

2
Немає легшого шляху?
guettli

3
Якщо ви використовуєте формат ps etimesзамість lstartвас, ви отримаєте пройдений час у секундах, який трохи легше перейти date -d -999seconds.
meuh

@meuh, так, це було б трохи коротше, я зробив оновлення
RomanPerekhrest

@guettli, не можу назвати це простіше, але у вас трохи коротший шлях
RomanPerekhrest

4

Ви можете сортувати за:

ps -eo lstart,pid,cmd --sort=start_time

Дякую, я продовжив своє запитання. Я також хочу формат дати iso.
гуетлі

2

Зауважте, що lstartце не одна зі стандартних psколонок Unix .

Не всі системи мають її, і вихід відрізняється між реалізаціями та, можливо, між локалями.

Наприклад, на FreeBSD або з psз procps-ng(як правило , знайти на не вбудовується Linux-систем на базі) і на Cмісцевості, ви отримаєте:

Wed Nov  1 12:36:15 2017

На macOS:

Wed  1 Nov 12:36:15 2017

Крім того, оскільки це не дає вам зміщення GMT, вихід є неоднозначним у часових поясах, які впроваджують DST (де є одна година протягом року, коли одні й ті самі дати трапляються двічі) і не завжди сортуються хронологічно.

Тут, ви можете змусити час бути UTC і використовувати perl«s 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=)
)

Або з bash(або zsh) лише в Linux та 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сприймається як запущений одночасно, sleep 234навіть якщо це було запущено 4 секунди пізніше. Це тому, що той процес 9388 спочатку був запущений sh(і чекав 4 секунди sleep 4) перед його виконанням sleep 123(а до цього він запускав zshкод так, як він був роздвоєний моєю інтерактивною оболонкою, тому в різні моменти часу для цього процесу у вас буде видно у psвисновку:, zshто sh, то sleep).


1
Спасибі за вашу відповідь. Зараз у мене більше запитань, ніж раніше. Я подумав, що існує легке і просте рішення.
guettli

1

Ось реалізація з більш високою продуктивністю (не потрібно виконувати новий процес у рядку):

ps -eo etimes,pid,args --sort=etimes | awk 'BEGIN{now=systime()} {$1=strftime("%Y-%m-%d %H:%M:%S", now-$1); print $0}'

і це дозволяє також досить легко змінювати впорядкування стовпців. Наприклад, pidперший і початковий час як другий стовпець:

ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.