Respostas:
Existe uma maneira de saída
lstart
no formato ISO comoYYYY-MM-DD HH:MM:SS
?
Com awk
+ date
cooperação:
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 }'
Abordagem alternativa usando a palavra-chave ps etimes
(tempo decorrido desde o início do processo, em segundos):
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
- a diferença entre o registro de data e hora atual e elapsed
o valor do registro de data e hora do processoetimes
vez de lstart
obter o tempo decorrido em segundos, é um pouco mais fácil de passar date -d -999seconds
.
Você pode classificar com:
ps -eo lstart,pid,cmd --sort=start_time
Observe que lstart
não é uma das ps
colunas padrão do Unix .
Nem todos os sistemas possuem um, e a saída varia entre implementações e potencialmente entre localidades.
Por exemplo, no FreeBSD ou com o ps
from procps-ng
(como normalmente encontrado em sistemas baseados no Linux não incorporados) e a C
localidade, você obtém:
Wed Nov 1 12:36:15 2017
No macOS:
Wed 1 Nov 12:36:15 2017
Além disso, como não fornece o deslocamento GMT, a saída é ambígua nos fusos horários que implementam o horário de verão (onde há uma hora durante o ano em que as mesmas datas ocorrem duas vezes) e nem sempre são ordenados cronologicamente.
Aqui, você pode forçar o horário a ser UTC e usar perl
o Date::Manip
módulo para analisar a data de uma maneira que compreenda diferentes formatos naturais:
(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
)
Ou com o ksh93
qual também reconhece esses formatos de data:
(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
)
(cuidado, retira os espaços em branco finais de cada linha)
Ou com zsh
e 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=)
)
Ou com bash
(ou zsh
) apenas no Linux e com 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=)"
)
Lembre-se também de que a hora de início do processo não é necessariamente a mesma da última vez que o processo executou um comando, pois os processos geralmente podem executar mais de um comando durante a vida útil (aqueles que não o fazem geralmente são aqueles que nunca executam um comando) . Em outras palavras, não corresponde necessariamente à hora em que o comando ( args
campo, o equivalente padrão de cmd
) foi iniciado.
$ 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
Veja como sleep 123
é visto como iniciado ao mesmo tempo como se sleep 234
tivesse sido iniciado 4 segundos depois. Isso ocorre porque o processo 9388 estava sendo executado inicialmente sh
(e aguardando 4 segundos sleep 4
) antes de ser executado sleep 123
(e antes disso, ele estava executando o zsh
código conforme foi bifurcado pelo meu shell interativo, portanto, em diferentes momentos no tempo, para esse processo, você teria visto na ps
saída:, zsh
então sh
, então sleep
).
Aqui está uma implementação com maior desempenho (não é necessário executar um novo processo por linha):
ps -eo etimes,pid,args --sort=etimes | awk 'BEGIN{now=systime()} {$1=strftime("%Y-%m-%d %H:%M:%S", now-$1); print $0}'
e isso também permite alterar facilmente a ordem das colunas. Por exemplo, pid
primeiro e hora de início como segunda coluna:
ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
lstart
esse formato é estranho? É perto da RFC 2822, mas com o ano no final.