sortie ps avec format de date iso?


9

Je voudrais trier cette sortie par lstart(début du processus):

ps -eo lstart,pid,cmd 

Existe-t-il un moyen de sortir lstart au format ISO comme AAAA-MM-JJ HH: MM: SS?

Mais le tri seul ne le résout pas. J'aimerais vraiment avoir le format de date ISO.


Pourquoi lstartun tel format bizarre. C'est proche de RFC 2822 mais avec l'année à la fin.
vaughan

Réponses:


10

Existe-t-il un moyen de sortie lstartau format ISO comme YYYY-MM-DD HH:MM:SS?

Avec awk+ datecoopération:

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

Approche alternative à l'aide du mot clé ps etimes (temps écoulé depuis le démarrage du processus, en secondes):

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- différence entre l'horodatage actuel et l' elapsedheure, donnera la valeur d' horodatage du processus

2
N'y a-t-il pas de moyen plus simple?
guettli

3
Si vous utilisez le format ps etimesau lieu de lstartvous obtenez le temps écoulé en secondes, ce qui est un peu plus facile à passer date -d -999seconds.
meuh

@meuh, oui, ce serait un peu plus court, j'ai fait une mise à jour
RomanPerekhrest

@guettli, ne peut pas l'appeler plus facilement, mais vous avez un peu plus court
RomanPerekhrest

4

Vous pouvez trier avec:

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

Merci, j'ai étendu ma question. Je veux aussi le format de date iso.
guettli

2

Notez que ce lstartn'est pas l'une des pscolonnes Unix standard .

Tous les systèmes n'en ont pas et la sortie varie entre les implémentations et potentiellement entre les paramètres régionaux.

Par exemple, sur FreeBSD ou avec le psfrom procps-ng(comme on le trouve généralement sur les systèmes Linux non intégrés) et les Cparamètres régionaux, vous obtiendrez:

Wed Nov  1 12:36:15 2017

Sur macOS:

Wed  1 Nov 12:36:15 2017

De plus, comme il ne vous donne pas le décalage GMT, la sortie est ambiguë dans les fuseaux horaires qui implémentent l'heure d'été (où il y a une heure dans l'année où les mêmes dates se produisent deux fois) et ne trient pas toujours chronologiquement.

Ici, vous pouvez forcer les heures à être UTC et utiliser perlle Date::Manipmodule de pour analyser la date d'une manière qui comprend différents formats naturels:

(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 avec ksh93lequel reconnaît également ces formats de date:

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

(attention, il supprime les blancs de fin de chaque ligne)

Ou avec zshet 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 avec bash(ou zsh) sur Linux uniquement et avec 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=)"
)

Sachez également que l'heure de début du processus n'est pas nécessairement la même que la dernière fois que le processus a exécuté une commande car les processus peuvent généralement exécuter plus d'une commande au cours de leur vie (ceux qui ne le sont généralement pas ceux qui n'exécutent jamais une commande) . En d'autres termes, cela ne correspond pas nécessairement au moment où la commande ( argschamp, l'équivalent standard de cmd) a été lancée.

$ 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

Voyez comment sleep 123est considéré comme démarré en même temps que sleep 234même s'il a été démarré 4 secondes plus tard. C'est parce que ce processus 9388 était initialement en cours d'exécution sh(et attendait 4 secondes sleep 4) avant d'être exécuté sleep 123(et avant cela, il exécutait du zshcode tel qu'il était bifurqué par mon shell interactif, donc à différents moments, pour ce processus, vous auriez vu dans la pssortie:, zshalors sh, alors sleep).


1
Merci pour votre réponse. Maintenant, j'ai plus de questions qu'auparavant. Je pensais qu'il y avait une solution facile et simple.
guettli

1

Voici une implémentation avec des performances plus élevées (n'a pas besoin d'exécuter un nouveau processus par ligne):

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

et cela permet aussi de changer assez facilement l'ordre des colonnes. Par exemple, la pidpremière et l'heure de début dans la deuxième colonne:

ps -eo pid,etimes,args --sort=etimes | awk 'BEGIN{now=systime()} {$2=strftime("%Y-%m-%d %H:%M:%S", now-$2); print $0}'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.