Risposte:
C'è un modo per produrre
lstartin formato ISO comeYYYY-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 processoetimesinvece di lstartottenere 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 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).
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}'
lstartha un formato così strano. È vicino alla RFC 2822 ma con un anno alla fine.