Risposte:
C'è un modo per produrre
lstart
in formato ISO comeYYYY-MM-DD HH:MM:SS
?
Con awk
+ date
cooperazione:
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 elapsed
tempo, fornirà il valore timestamp del processoetimes
invece di lstart
ottenere il tempo trascorso in secondi che è un po 'più facile da passare date -d -999seconds
.
Puoi ordinare con:
ps -eo lstart,pid,cmd --sort=start_time
Nota che lstart
non è una delle ps
colonne 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 ps
da procps-ng
(come in genere si trova su sistemi basati su Linux non integrati) e le C
impostazioni 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 perl
il Date::Manip
modulo 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 ksh93
quale 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 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=)
)
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 ( args
campo, 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 234
se 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 zsh
codice come era stato biforcuto dalla mia shell interattiva, quindi in diversi punti nel tempo, per quel processo, avresti visto ps
nell'output:, zsh
quindi sh
, quindi sleep
).
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 pid
prima 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}'
lstart
ha un formato così strano. È vicino alla RFC 2822 ma con un anno alla fine.