uscita ps con formato data ISO?


9

Vorrei ordinare questo output per lstart(inizio del processo):

ps -eo lstart,pid,cmd 

Esiste un modo per avviare lstart in formato ISO come AAAA-MM-GG HH: MM: SS?

Ma l'ordinamento da solo non lo risolve. Mi piacerebbe davvero avere un formato data ISO.


Perché lstartha un formato così strano. È vicino alla RFC 2822 ma con un anno alla fine.
vaughan,

Risposte:


10

C'è un modo per produrre lstartin formato ISO come YYYY-MM-DD HH:MM:SS?

Con awk+ datecooperazione:

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 }'

Approccio alternativo utilizzando la parola chiave ps etimes (tempo trascorso dall'inizio del processo, in secondi):

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- la differenza tra il timestamp corrente e il elapsedtempo, fornirà il valore timestamp del processo

2
Non c'è modo più semplice?
Guettli,

3
Se usi il formato ps etimesinvece di lstartottenere il tempo trascorso in secondi che è un po 'più facile da passare date -d -999seconds.
Meuh

@meuh, sì, sarebbe un po 'più breve, ho fatto un aggiornamento
RomanPerekhrest

@guettli, non posso dirlo più facilmente, ma hai un modo un po 'più breve
RomanPerekhrest

4

Puoi ordinare con:

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

Grazie, ho esteso la mia domanda. Voglio anche il formato data iso.
Guettli,

2

Nota che lstartnon è una delle pscolonne Unix standard .

Non tutti i sistemi ne hanno uno e l'output varia tra implementazioni e potenzialmente tra locali.

Ad esempio, su FreeBSD o con il psda procps-ng(come in genere si trova su sistemi basati su Linux non integrati) e le Cimpostazioni locali, otterrai:

Wed Nov  1 12:36:15 2017

Su macOS:

Wed  1 Nov 12:36:15 2017

Inoltre, poiché non ti dà l'offset GMT, l'output è ambiguo in fusi orari che implementano l'ora legale (dove c'è un'ora durante l'anno in cui le stesse date si verificano due volte) e non si ordinano sempre in ordine cronologico.

Qui, potresti forzare i tempi a essere UTC e utilizzare perlil Date::Manipmodulo per analizzare la data in modo da comprendere diversi formati naturali:

(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
)

O con il ksh93quale riconosce anche quei formati di 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
)

(attenzione, rimuove gli spazi vuoti finali da ogni riga)

O con 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=)
)

O con bash(o zsh) solo su Linux e con 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=)"
)

Si noti inoltre che l'ora di inizio del processo non è necessariamente la stessa dell'ultima volta in cui il processo ha eseguito un comando poiché i processi possono generalmente eseguire più di un comando durante la loro vita (quelli che non sono generalmente quelli che non eseguono mai un comando) . In altre parole, non corrisponde necessariamente al momento in cui è stato avviato il comando ( argscampo, l'equivalente standard di 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

Scopri come sleep 123è stato avviato come sleep 234se fosse stato avviato anche se è stato avviato 4 secondi dopo. Questo perché il processo 9388 era inizialmente in esecuzione sh(e in attesa di 4 secondi sleep 4) prima che fosse eseguito sleep 123(e prima ancora, stava eseguendo il zshcodice come era stato biforcuto dalla mia shell interattiva, quindi in diversi punti nel tempo, per quel processo, avresti visto psnell'output:, zshquindi sh, quindi sleep).


1
La ringrazio per la risposta. Ora ho più domande di prima. Ho pensato che ci fosse una soluzione facile e semplice.
Guettli,

1

Ecco un'implementazione con prestazioni più elevate (non è necessario eseguire un nuovo processo per riga):

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

e ciò consente anche di modificare facilmente l'ordinamento delle colonne. Ad esempio pidprima e ora di inizio come seconda colonna:

ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.