Dmesg zaman damgasını özel tarih biçimine dönüştürün


112

Dmesg zaman damgasını anlamaya çalışıyorum ve bunu java tarihi / özel tarih biçimine dönüştürmek için onu dönüştürmekte zorlanıyorum.

herhangi bir yardım çok takdir edilmektedir.

Örnek dmesg günlüğü:

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

Teşekkürler!

Yanıtlar:


180

dmesgZaman damgasını anlamak oldukça basittir: Çekirdeğin başlamasından bu yana geçen saniye cinsinden zamandır. Böylece, başlatma süresine ( uptime) sahip olarak , saniyeleri toplayabilir ve bunları istediğiniz formatta gösterebilirsiniz.

Ya da daha iyisi, -Tkomut satırı seçeneğini kullanabilir dmesgve insan tarafından okunabilir biçimi ayrıştırabilirsiniz.

Gönderen adam sayfası :

-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.

10
Hangi komut -T'yi kabul eder? Benim dmesg'm bilmiyor, manpage de söylemiyor. (Linux Mint Debian Sürümü).
gyorgyabraham

1
Maden (yapar dmesgden util-linux 2.20.113.04 Ubuntu altında)

2
Redhat ve / veya oracle linux 5.6'da mevcut değil, rpm -qf /bin/dmesg => util-linux-2.13-0.56.0.2.el5
michael

7
Bu seçenek util-linux 2.20Sürüm Notlarına göre göründü : ftp.kernel.org/pub/linux/utils/util-linux/v2.20/…
ks1322

1
@xealits, takip için teşekkürler, çok naziksiniz :) Soruyla ilgili olarak, anlayış kısmının küçük olduğunu ve "bunu java tarih / özel tarih formatına dönüştürmek için bunu dönüştürmek" olduğunu düşünüyorum. temel kısımdı, ancak fikriniz farklı olabilir. İyi günler;)

32

Dr cevabının yardımıyla , dönüşümü .bashrc dosyanıza koymak için bir geçici çözüm yazdım. Herhangi bir zaman damganız yoksa veya zaten doğru zaman damgalarınız yoksa hiçbir şeyi bozmaz.

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

Ayrıca, dmesg zaman damgası dönüştürme mantığı ve hiçbiri olmadığında zaman damgalarının nasıl etkinleştirileceği hakkında iyi bir okuma: https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk92677


küçük iyileştirme: ardışık düzendeki 'kuyruk -1'i kaldırabilir ve sadece awk'nin satırları yemesine ve tamponundaki son satırdan yazdırmasına izin verebilirsiniz. local dmesg_bin=$(type -a dmesg | awk 'END { print $NF }')
Brian Onn

@Lucas: $ (hangi dmesg) yerine 'type -a dmesg | ...' kullanarak açıklayabilir misiniz? Bu yolu elde etmek için 3 aşamalı bir borunun avantajı var mı?
Stabledog

@Stabledog: güzel soru. Neden typeover kullanıldığına dair bir açıklama için bu soruyawhich bakın . Yine de işe yaramaz üçlü pipodan kaçınmak için cevabımı düzenledim.
Lucas Cimon

bu bash / perl pasajı benim için çalıştı, bakmam gereken eski bir RHEL5.7 makinem var ve dmesg'in zaman damgasını insan zamanında yazdırma seçeneği yok.
Paul M

17

RHEL / CentOS 6 gibi "dmesg-T" içermeyen sistemler için, daha önce lucas-cimon tarafından sağlanan "dmesg_with_human_timestamps" işlevini beğendim . Yine de büyük çalışma süresine sahip bazı kutularımızda biraz sorun var. Dmesg'deki çekirdek zaman damgalarının, ayrı CPU'lar tarafından tutulan bir çalışma süresi değerinden türetildiği ortaya çıktı. Zamanla bu, gerçek zamanlı saatle senkronize olmaz. Sonuç olarak, son dmesg girdileri için en doğru dönüştürme, / proc / uptime yerine CPU saatine dayalı olacaktır. Örneğin, belirli bir CentOS 6.6 kutusunda:

# 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

CPU çalışma süresinin milisaniye cinsinden hesaba katılması, burada yaklaşık 5 1/2 saatlik bir ofset var. Bu yüzden komut dosyasını gözden geçirdim ve bu süreçte onu yerel bash'a dönüştürdüm:

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

İşlev zsh'da çalışmadı. Bunu uygun bir şekilde yapmalıydım. Bununla birlikte, 221 günlük çalışma süresi olan bir kutuda, bu çözümün gerçek dakikasına kadar zaman damgası vardı. Diğer çözümler, temel neden olayının gün içinde 2 saatten daha erken gerçekleştiğini gösterdi. Teşekkürler Allen. Öğleden sonramı kurtardın.
Trenton

RHEL5.x makinelerinde / proc / sched_debug :-(
Paul M

14

Bu yüzden KevZero daha az karmaşık bir çözüm istedi, ben de şunu buldum:

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'

İşte bir örnek:

$ 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

Biraz daha iyi performans göstermesini istiyorsanız, zaman damgasını proc'tan bir değişkene koyun :)


4

Dmesg'nin son sürümlerinde, sadece arayabilirsiniz dmesg -T.


3
Aynı cevap RC tarafından sizinkinden iki yıl önce de verilmişti.
josch

4

Eğer yoksa -Tseçeneğini dmesgAndoid örneğin, kullanmak gibi busyboxsürümünü. Aşağıdaki bazı diğer sorunları da çözer:

  1. [0.0000]Biçimi yanlış renk bilgileri gibi görünüyor, önek gibi bir şeye öncesinde <6>.
  2. Kayan sayılardan tamsayılar yapın.

Bu blog gönderisinden ilham almıştır .

#!/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                                                                                                                      

Bununla birlikte, bu uygulamanın oldukça yavaş olduğunu unutmayın.


3

/ proc / stat içindeki "btime" 'a başvurmanız gerekir, bu, sistemin en son başlatıldığı Unix dönemi zamanıdır. Daha sonra bu sistem önyükleme zamanını temel alabilir ve ardından her olay için zaman damgasını hesaplamak için dmesg cinsinden verilen geçen saniyeleri ekleyebilirsiniz.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.