web-dev-qa-db-fra.com

Conversion de l'horodatage dmesg au format de date personnalisé

J'essaye de comprendre le timestamp de dmesg et trouve difficile de convertir cela pour le changer en Java date/format de date personnalisé.

toute aide est très appréciée.

Exemple de log de dmesg:

[14614.647880] airo(eth1): link lost (missed beacons)

Merci!

98
ukanth

Comprendre dmesg l’horodatage est assez simple: c’est le temps en secondes depuis le démarrage du noyau. Ainsi, ayant le temps de démarrage (uptime), vous pouvez additionner les secondes et les afficher dans le format de votre choix.

Ou mieux, vous pouvez utiliser le -T _ option et analyser le format lisible par l’homme.

De la page de manuel :

-T, --ctime
    Print human readable timestamps. The timestamp could be inaccurate!

    The time source used for the logs is not updated after system SUSPEND/RESUME.
154
user180100

Avec l’aide de dr answer, j’ai écrit une solution de contournement qui rend la conversion à mettre dans votre .bashrc. Cela ne casse rien si vous n'avez pas d'horodatage ou si les correctifs sont déjà corrects.

dmesg_with_human_timestamps () {
    $(type -P dmesg) "$@" | Perl -w -e 'use strict;
        my ($uptime) = do { local @ARGV="/proc/uptime";<>}; ($uptime) = ($uptime =~ /^(\d+)\./);
        foreach my $line (<>) {
            printf( ($line=~/^\[\s*(\d+)\.\d+\](.+)/) ? ( "[%s]%s\n", scalar localtime(time - $uptime + $1), $2 ) : $line )
        }'
}
alias dmesg=dmesg_with_human_timestamps

En outre, une bonne lecture de la logique de conversion dmesg timestamp et comment activer les horodatages lorsqu'il n'y en a pas: https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk92677

30
Lucas Cimon

Pour les systèmes sans "dmesg -T" tels que RHEL/CentOS 6, j’aimais la fonction "dmesg_with_human_timestamps" fournie par lucas-cimon auparavant. Il y a cependant quelques problèmes avec certaines de nos boîtes avec un temps de disponibilité important. Il s'avère que les horodatages du noyau dans dmesg sont dérivés d'une valeur de temps de disponibilité conservée par des processeurs individuels. Au fil du temps, cela ne correspond plus à l'horloge en temps réel. En conséquence, la conversion la plus précise pour les entrées dmesg récentes sera basée sur l'horloge du processeur plutôt que sur/proc/uptime. Par exemple, sur une boîte CentOS 6.6 particulière ici:

# grep "\.clock" /proc/sched_debug  | head -1
  .clock                         : 32103895072.444568
# uptime
 15:54:05 up 371 days, 19:09,  4 users,  load average: 3.41, 3.62, 3.57
# cat /proc/uptime
32123362.57 638648955.00

Compte tenu du temps de disponibilité du processeur exprimé en millisecondes, il existe un décalage de près de 5 1/2 heures. J'ai donc revu le script et l'ai converti en bash natif:

dmesg_with_human_timestamps () {
    FORMAT="%a %b %d %H:%M:%S %Y"

    now=$(date +%s)
    cputime_line=$(grep -m1 "\.clock" /proc/sched_debug)

    if [[ $cputime_line =~ [^0-9]*([0-9]*).* ]]; then
        cputime=$((BASH_REMATCH[1] / 1000))
    fi

    dmesg | while IFS= read -r line; do
        if [[ $line =~ ^\[\ *([0-9]+)\.[0-9]+\]\ (.*) ]]; then
            stamp=$((now-cputime+BASH_REMATCH[1]))
            echo "[$(date +"${FORMAT}" --date=@${stamp})] ${BASH_REMATCH[2]}"
        else
            echo "$line"
        fi
    done
}

alias dmesgt=dmesg_with_human_timestamps
15
Allen Belletti

Donc KevZero a demandé une solution moins efficace, alors j’ai proposé ce qui suit:

sed -r 's#^\[([0-9]+\.[0-9]+)\](.*)#echo -n "[";echo -n $(date --date="@$(echo "$(grep btime /proc/stat|cut -d " " -f 2)+\1" | bc)" +"%c");echo -n "]";echo -n "\2"#e'

Voici un exemple:

$ dmesg|tail | sed -r 's#^\[([0-9]+\.[0-9]+)\](.*)#echo -n "[";echo -n $(date --date="@$(echo "$(grep btime /proc/stat|cut -d " " -f 2)+\1" | bc)" +"%c");echo -n "]";echo -n "\2"#e'
[2015-12-09T04:29:20 COT] cfg80211:   (57240000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 0 mBm), (N/A)
[2015-12-09T04:29:23 COT] wlp3s0: authenticate with dc:9f:db:92:d3:07
[2015-12-09T04:29:23 COT] wlp3s0: send auth to dc:9f:db:92:d3:07 (try 1/3)
[2015-12-09T04:29:23 COT] wlp3s0: authenticated
[2015-12-09T04:29:23 COT] wlp3s0: associate with dc:9f:db:92:d3:07 (try 1/3)
[2015-12-09T04:29:23 COT] wlp3s0: RX AssocResp from dc:9f:db:92:d3:07 (capab=0x431 status=0 aid=6)
[2015-12-09T04:29:23 COT] wlp3s0: associated
[2015-12-09T04:29:56 COT] thinkpad_acpi: EC reports that Thermal Table has changed
[2015-12-09T04:29:59 COT] i915 0000:00:02.0: BAR 6: [??? 0x00000000 flags 0x2] has bogus alignment
[2015-12-09T05:00:52 COT] thinkpad_acpi: EC reports that Thermal Table has changed

Si vous voulez que cela fonctionne un peu mieux, mettez plutôt le timestamp de proc dans une variable :)

12
runejuhl

Dans les versions récentes de dmesg, vous pouvez simplement appeler dmesg -T.

5
Steffen Heil

vous devrez faire référence au "btime" dans/proc/stat, qui correspond à l'heure de l'époque Unix au moment du dernier démarrage du système. Vous pouvez ensuite vous baser sur cette heure de démarrage du système, puis ajouter les secondes écoulées données dans dmesg pour calculer l’horodatage de chaque événement.

3
imcom

Si vous n'avez pas l'option -T Pour dmesg comme par exemple sur Andoid, vous pouvez utiliser la version busybox. Ce qui suit résout également quelques autres problèmes:

  1. Le format [0.0000] Est précédé de quelque chose qui ressemble à une information de couleur mal placée, avec des préfixes comme <6>.
  2. Faire des entiers à partir de floats.

Il est inspiré par cet article de blog .

#!/bin/sh                                                                                                               
# Translate dmesg timestamps to human readable format                                                                   

# uptime in seconds                                                                                                     
uptime=$(cut -d " " -f 1 /proc/uptime)                                                                                  

# remove fraction                                                                                                       
uptime=$(echo $uptime | cut -d "." -f1)                                                                                 

# run only if timestamps are enabled                                                                                    
if [ "Y" = "$(cat /sys/module/printk/parameters/time)" ]; then                                                          
  dmesg | sed "s/[^\[]*\[/\[/" | sed "s/^\[[ ]*\?\([0-9.]*\)\] \(.*\)/\\1 \\2/" | while read timestamp message; do      
    timestamp=$(echo $timestamp | cut -d "." -f1)                                                                       
    ts1=$(( $(busybox date +%s) - $uptime + $timestamp ))                                                               
    ts2=$(busybox date -d "@${ts1}")                                                                                    
    printf "[%s] %s\n" "$ts2" "$message"                                                                                
  done                                                                                                                  
else                                                                                                                    
  echo "Timestamps are disabled (/sys/module/printk/parameters/time)"                                                   
fi                                                                                                                      

Notez cependant que cette implémentation est assez lente.

3
Anne van Rossum

Avec les anciennes distributions Linux, une autre option consiste à utiliser un script de wrapping, par exemple. en Perl ou en Python.

Voir les solutions ici:

http://linuxaria.com/article/how-to-make-dmesg-timestamp-human-readable?lang=enhttp://jmorano.moretrix.com/2012/ 03/dmesg-human-lisible-timestamps /

3
Aliaksei Ramanau