saída ps com formato de data iso?

9

Gostaria de classificar essa saída por lstart(início do processo):

ps -eo lstart,pid,cmd 

Existe uma maneira de gerar lstart no formato ISO como AAAA-MM-DD HH: MM: SS?

Mas classificar sozinho não resolve. Eu realmente gostaria de ter o formato de data ISO.

guettli
fonte
Por que lstartesse formato é estranho? É perto da RFC 2822, mas com o ano no final.
Vaughan

Respostas:

10

Existe uma maneira de saída lstartno formato ISO como YYYY-MM-DD HH:MM:SS?

Com awk+ datecooperaçã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 elapsedo valor do registro de data e hora do processo
RomanPerekhrest
fonte
2
Não existe uma maneira mais fácil?
guettli
3
Se você usar o formato ps em etimesvez de lstartobter o tempo decorrido em segundos, é um pouco mais fácil de passar date -d -999seconds.
meuh
@meuh, sim, isso seria um pouco mais curto, eu fiz uma atualização
RomanPerekhrest
@guettli, não pode chamá-lo mais fácil, mas você tem um pouco mais curto caminho
RomanPerekhrest
4

Você pode classificar com:

ps -eo lstart,pid,cmd --sort=start_time
Ipor Sircer
fonte
Obrigado, estendi minha pergunta. Também quero formato de data ISO.
guettli
2

Observe que lstartnão é uma das pscolunas 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 psfrom procps-ng(como normalmente encontrado em sistemas baseados no Linux não incorporados) e a Clocalidade, 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 perlo Date::Manipmó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 ksh93qual 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 zshe 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 ( argscampo, 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 234tivesse 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 zshcódigo conforme foi bifurcado pelo meu shell interativo, portanto, em diferentes momentos no tempo, para esse processo, você teria visto na pssaída:, zshentão sh, então sleep).

Stéphane Chazelas
fonte
1
Obrigado pela sua resposta. Agora eu tenho mais perguntas do que antes. Eu pensei que há uma solução fácil e simples.
guettli
1

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, pidprimeiro 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}'
Mikko Rantalainen
fonte