Перетворити часову позначку dmesg у спеціальний формат дати


111

Я намагаюся зрозуміти часову позначку dmesg і мені важко перетворити її, щоб змінити її на формат дати / спеціальний формат дати.

будь-яка допомога дуже цінується.

Зразок журналу dmesg:

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

Дякую!

Відповіді:


179

Розуміння dmesgпозначки часу досить проста: час запускається в секунду з моменту запуску ядра. Отже, маючи час запуску ( uptime), ви можете додати секунди та показати їх у будь-якому форматі, який вам подобається.

Або ще краще, ви можете скористатися параметром -Tкомандного рядка dmesgта проаналізувати читаний для людини формат.

На сторінці чоловіка :

-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
Яка команда приймає -T? Мій dmesg ні, ні manpage не говорить про це. (Linux Mint Debian Edition).
gyorgyabraham

1
Шахта робить ( dmesgз- util-linux 2.20.1під Ubuntu 13.04)

2
Не доступно в Redhat та / або Oracle linux 5.6, rpm -qf /bin/dmesg => util-linux-2.13-0.56.0.2.el5
michael

7
Цей параметр з’явився у util-linux 2.20примітках до випуску: ftp.kernel.org/pub/linux/utils/util-linux/v2.20/…
ks1322

1
@xealits спасибі за подальші дії, це приємно для вас :) Щодо питання, я вважаю, що розуміюча частина незначна, і "перетворіть її, щоб змінити її на формат дати / спеціальний формат дати". була основна частина, але ваша думка може відрізнятися. Приємного дня;)

32

За допомогою dr відповіді я написав вирішення, яке робить перетворення, яке потрібно розмістити у вашому .bashrc. Це нічого не порушить, якщо у вас немає жодної часової позначки або вже правильних часових позначок.

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

Також добре прочитати логіку перетворення часових міток dmesg та як увімкнути часові позначки, коли таких немає: https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk92677


незначне поліпшення: ви можете видалити "хвіст -1" у конвеєрі та просто дозволити пробуджувати рядки та друкувати з остаточного рядка в буфері. local dmesg_bin=$(type -a dmesg | awk 'END { print $NF }')
Брайан Онн

@Lucas: чи можете ви пояснити, використовуючи 'type -a dmesg | ...' замість $ (який dmesg)? Чи є перевага 3-ступінчастій трубі, щоб отримати цей шлях?
Stabledog

@Stabledog: гарне запитання. Пояснення про те, чому використовувати typeнад which, див. Це питання . Я відредагував свою відповідь, щоб уникнути марної потрійної труби.
Лукас Кімон

цей фрагмент bash / perl працював на мене, у мене є стара машина RHEL5.7, яку я повинен доглядати, і dmesg не має можливості друкувати часові позначки в людський час.
Пол М

17

Для систем без "dmesg -T", таких як RHEL / CentOS 6, мені сподобалася функція "dmesg_with_human_timestamps", яку надає lucas-cimon раніше. З деякими нашими коробками з великою тривалістю роботи, проте, це неприємності. Виявляється, часові позначки ядра в dmesg є похідним значенням, яке зберігається окремими процесорами. З часом це виходить із синхронізації з годинником у режимі реального часу. Як результат, найточніша конверсія для останніх записів dmesg буде базуватися на тактовій частоті процесора, а не / proc / uptime. Наприклад, на певному вікні CentOS 6.6 тут:

# 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

Облік часу роботи процесора в мілісекундах, тут є компенсація майже 5 1/2 годин. Тому я переглянув сценарій і перетворив його на рідний bash в процесі:

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

Функція не працювала в zsh. Довелося це робити у власних силах. Це означає, що в коробці з 221 робочим днем ​​роботи це рішення позначало час до фактичної хвилини. Інші рішення показали, що перша подія відбулася на 2 години раніше. Спасибі, Аллен. Ти врятував мій день.
Трентон

На машинах RHEL5.x, здається, немає / proc / sched_debug :-(
Paul M

14

Тож KevZero попросив менш дивне рішення, тому я придумав таке:

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'

Ось приклад:

$ 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

Якщо ви хочете, щоб він працював трохи краще, замість цього помістіть часову позначку від proc: :)


4

В останніх версіях dmesg можна просто зателефонувати dmesg -T.


3
Таку ж відповідь уже дав RC за два роки до вашого.
Джош

4

Якщо у вас немає такої -Tможливості, dmesgяк, наприклад, на Andoid, ви можете використовувати busyboxверсію. Наступне вирішує і деякі інші питання:

  1. [0.0000]Формат передує то , що виглядає як недоречна інформація про кольорі, префікси<6> .
  2. Складіть цілі числа з поплавків.

Це надихає ця публікація в блозі .

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

Однак зауважте, що ця реалізація є досить повільною.


3

вам потрібно буде посилатись на "btime" в / proc / stat, який є епохою часу Unix, коли система була останньо завантажена. Тоді ви можете базуватись на час завантаження системи, а потім додати минулі секунди, вказані в dmesg, щоб обчислити часові позначки для кожної події.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.