Відповіді:
Чи є спосіб вивести такий
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
замість lstart
вас, ви отримаєте пройдений час у секундах, який трохи легше перейти date -d -999seconds
.
Ви можете сортувати за:
ps -eo lstart,pid,cmd --sort=start_time
Зауважте, що 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
).
Ось реалізація з більш високою продуктивністю (не потрібно виконувати новий процес у рядку):
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}'
lstart
такий формат wierd. Він близький до RFC 2822, але з кінцем року.