Ubah stempel waktu dmesg ke format tanggal kustom

112

Saya mencoba memahami stempel waktu dmesg dan merasa sulit untuk mengubahnya menjadi tanggal java / format tanggal kustom.

bantuan apa pun sangat dihargai.

Contoh log dmesg:

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

Terima kasih!

ukanth
sumber

Jawaban:

180

Memahami dmesgstempel waktu cukup sederhana: ini adalah waktu dalam hitungan detik sejak kernel dimulai. Jadi, saat memulai ( uptime), Anda dapat menambahkan detik dan menampilkannya dalam format apa pun yang Anda suka.

Atau lebih baik, Anda dapat menggunakan -Topsi baris perintah dmesgdan mengurai format yang dapat dibaca manusia.

Dari halaman manual :

-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.
drescherjm
sumber
10
Perintah apa yang menerima -T? Dmesg saya tidak, tidak ada halaman manual yang memberitahukannya. (Linux Mint Debian Edition).
gyorgyabraham
1
Punyaku tidak ( dmesgdari util-linux 2.20.1bawah Ubuntu 13.04)
2
Tidak tersedia di redhat dan / atau oracle linux 5.6, rpm -qf /bin/dmesg => util-linux-2.13-0.56.0.2.el5
michael
7
Opsi ini muncul di util-linux 2.20, menurut Catatan Rilis: ftp.kernel.org/pub/linux/utils/util-linux/v2.20/…
ks1322
1
@xealits terima kasih atas tindak lanjutnya, terima kasih banyak :) Mengenai pertanyaan itu, saya pikir bagian pemahamannya kecil dan "ubah itu menjadi ubah ke tanggal java / format tanggal khusus." adalah bagian intinya, tetapi pendapat Anda mungkin berbeda. Semoga harimu menyenangkan;)
32

Dengan bantuan jawaban dr , saya menulis solusi yang membuat konversi menjadi .bashrc Anda. Ini tidak akan merusak apa pun jika Anda tidak memiliki stempel waktu atau stempel waktu yang sudah benar.

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

Juga, bacaan yang baik tentang logika konversi stempel waktu dmesg & cara mengaktifkan stempel waktu jika tidak ada: https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk92677

Lucas Cimon
sumber
perbaikan kecil: Anda dapat menghapus 'tail -1' di pipeline dan biarkan awk memakan garis dan mencetak dari baris terakhir di buffernya. local dmesg_bin=$(type -a dmesg | awk 'END { print $NF }')
Brian Onn
@ Lucas: dapatkah Anda menjelaskan menggunakan 'type -a dmesg | ...' daripada $ (which dmesg)? Apakah ada keuntungan dari pipa 3 tingkat untuk mendapatkan jalur tersebut?
Stabledog
@Stabledog: pertanyaan bagus. Untuk penjelasan tentang mengapa menggunakan typelebih which, lihat pertanyaan ini . Saya mengedit jawaban saya untuk menghindari pipa tripel yang tidak berguna.
Lucas Cimon
Potongan bash / perl ini bekerja untuk saya, saya memiliki mesin RHEL5.7 lama yang harus saya jaga dan dmesg tidak memiliki opsi untuk mencetak cap waktu dalam waktu manusia.
Paul M
17

Untuk sistem tanpa "dmesg -T" seperti RHEL / CentOS 6, saya menyukai fungsi "dmesg_with_human_timestamps" yang disediakan oleh lucas-cimon sebelumnya. Ini memiliki sedikit masalah dengan beberapa kotak kami dengan waktu aktif yang besar. Ternyata cap waktu kernel di dmesg berasal dari nilai waktu aktif yang disimpan oleh masing-masing CPU. Seiring waktu, ini tidak sinkron dengan jam waktu nyata. Hasilnya, konversi paling akurat untuk entri dmesg terbaru akan didasarkan pada jam CPU daripada / proc / uptime. Misalnya, pada kotak CentOS 6.6 di sini:

# 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

Penghitungan waktu aktif CPU dalam milidetik, ada offset hampir 5 1/2 jam di sini. Jadi saya merevisi skrip dan mengubahnya menjadi bash asli dalam proses:

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
Allen Belletti
sumber
Fungsi tidak berfungsi di zsh. Harus melakukannya dengan benar. Meskipun demikian, pada kotak dengan waktu aktif 221 hari, solusi ini memiliki waktu yang terukur hingga menit sebenarnya. Solusi lain menunjukkan akar masalah terjadi 2+ jam lebih awal pada hari itu. Terima kasih, Allen. Anda menyelamatkan sore saya.
Trenton
Mesin RHEL5.x tampaknya tidak memiliki / proc / sched_debug :-(
Paul M
14

Jadi KevZero meminta solusi yang tidak terlalu rumit , jadi saya datang dengan yang berikut:

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'

Berikut contohnya:

$ 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

Jika Anda ingin kinerjanya sedikit lebih baik, letakkan stempel waktu dari proc ke dalam variabel :)

runejuhl
sumber
4

Di versi terbaru dmesg, Anda bisa menelepon dmesg -T.

Steffen Heil
sumber
3
Jawaban yang sama sudah diberikan RC dua tahun sebelum Anda.
josch
4

Jika Anda tidak memiliki -Topsi dmesgseperti misalnya di Andoid, Anda dapat menggunakan busyboxversi tersebut. Berikut ini juga memecahkan beberapa masalah lain:

  1. The [0.0000]Format didahului oleh sesuatu yang tampak seperti informasi warna salah tempat, awalan seperti <6>.
  2. Buat bilangan bulat dari float.

Itu terinspirasi oleh posting blog ini .

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

Perhatikan, bagaimanapun, bahwa implementasi ini cukup lambat.

Anne van Rossum
sumber
3

Anda perlu mereferensikan "btime" di / proc / stat, yang merupakan waktu waktu Unix saat sistem di-boot terakhir. Kemudian Anda dapat mendasarkan pada waktu boot sistem tersebut dan kemudian menambahkan detik yang telah berlalu yang diberikan dalam dmesg untuk menghitung stempel waktu untuk setiap kejadian.

imcom
sumber