2011-05-26 21:55:11 +0000 2011-05-26 21:55:11 +0000
146
146

É possível `tail -f` a saída de `dmesg`?

Quero fazer algo como

dmesg | tail -f

mas não funciona:

Eu uso Mac OS X v10.6.7 (Snow Leopard). Ao fazer isso, tail sairá, em vez de monitorizar a saída.

Pergunto-me se existe uma forma de o fazer, ou um comando equivalente.

P.S., não me parece que um while loop seja uma boa ideia.

Respostas (11)

130
130
130
2011-05-26 22:04:06 +0000

Provavelmente está à procura de alguma combinação de mensagens de vários ficheiros de registo. Tente:

tail -f /var/log/{messages,kernel,dmesg,syslog}

…para obter uma boa visão geral do sistema. Se quiser mais ou menos do que isso, pesquise em que ficheiro de registo estão a ser colocadas as mensagens que deseja ver.

Também procure usar multitail para arquivar e código de cor e filtrar múltiplos ficheiros de registo de uma só vez.

Editar: Isto não foi muito relevante quando respondi a isto, mas como esta página recebe muitas visitas, penso que vale a pena mencionar que os sistemas mais recentes que executam systemd têm isto.

dmesg -w
56
56
56
2011-06-11 22:42:51 +0000

Basta fazer @##$%ing trabalho

  1. Quer imprimir a saída do dmesg, constantemente, imediatamente
  2. O dmesg está a imprimir o buffer do anel do núcleo (ver man dmesg)
  3. O buffer de anel de kernel é um ficheiro proc especial, /proc/kmsg (ver man proc)
  4. Ler /proc/kmsg directamente, ou seja cat /proc/kmsg.

Agora, se ler o manual amigável do proc, ele irá avisá-lo firmemente para deixar apenas um utilizador (que deve ser privilegiado) ler /proc/kmsg de cada vez. Qualquer que seja a implementação do syslog que tenha, deverá estar a fazer isto, e presumivelmente funciona com dmesg. Não sei, estou fora do meu alcance aqui, apenas parafraseando o manual. Portanto, embora esta seja a forma de “apenas fazer com que @#$% funcione”, considere primeiro os próximos métodos de casal.

Página humana aprovada: relógio + dmesg

Numa caixa de linux que uso com systemd init*, dmesg.log não é escrito com muita frequência, talvez nem um pouco? A melhor maneira que encontrei para ler continuamente o buffer de log do kernel é com watch. Algo parecido com isto deve fazê-lo começar (ajuste para quantas linhas cabem no seu terminal):

watch 'dmesg | tail -50'

relógio + dmesg + daemon + cauda -f

Uma solução mais complicada poderia usar relógio para escrever a saída do dmesg em ficheiro, que poderia então tail -f. Provavelmente quereria que isto funcionasse como um daemon. Um daemon adequado também gzip e rotacionaria os registos. O seguinte código de bash não está testado, não funciona, e apenas pretende transmitir uma ideia. @Brooks a resposta de Moisés tem uma versão funcional .

watch 'dmesg >> /var/log/dmesg.log | tail -1'

* tangente, porque esta é uma pergunta sobre um os de secretária de maçã: quando o systemd estiver por perto, não se preocupe com dmesg; use journalctl -xf (talvez c/ -n 100 para mostrar também as 100 linhas anteriores)

47
47
47
2014-03-28 14:27:08 +0000

No Linux, desde o kernel 3.5.0 que pode utilizar:

dmesg -w

Também em sistemas com systemd pode usar:

journalctl -kf
21
21
21
2012-07-20 21:45:27 +0000

Aqui está uma variante da resposta de djeikyb que é realmente testada, e corrige um par de bugs.

watch 'sudo dmesg -c >> /tmp/dmesg.log; tail -n 40 /tmp/dmesg.log'

O truque importante é que estamos a fazer dmesg -c&, o que limpa o buffer de anéis depois de imprimir - assim, de cada vez que passamos só estamos a imprimir o que é novo desde a última vez.

Terá de ser a raiz para o fazer, portanto o sudo. Há também uma correcção de bugs; em vez de tentarmos tanto descarregar a saída para um ficheiro como canalizá-la para a cauda (que não funciona), estamos apenas a ler a partir do ficheiro recém-escrito.

Poderíamos fazer apenas dmesg > /tmp/dmesg.log e escrever por cima do ficheiro inteiro a cada iteração, mas isso é muito I/O e também corre o risco de perder o ficheiro se o computador falhar no meio de uma escrita por cima.

Também se poderia fazer algo semelhante mais parecido com tail -f com um loop while que executa dmesg -c e sleep 1 para sempre (ver a resposta de Ben Harris). No entanto, uma vez que isto está de facto a limpar o buffer de mensagens do kernel enquanto está a correr, pode também querer canalizar as coisas para um ficheiro de registo, caso as queira mais tarde.

5
5
5
2012-11-05 13:45:51 +0000

Fi-lo antes de ver este post:

#!/usr/bin/env perl

use strict;
use warnings;

# "tail -f" for dmesg
# Keeps last printed line. Anything sorting "gt" will be newer

$|=1;

my $y = '';

while(1) {
    for my $k (`dmesg`) {
        if ($k gt $y) {
            print $k;
            $y = $k;
        }
    }
    sleep 1;
}
exit;
3
3
3
2013-03-05 08:26:53 +0000

Aqui estão algumas ideias para ambientes limitados

Ambientes tais como ambientes embutidos ou pré-boot, onde o relógio, cauda, gato, dd e outros comandos podem não estar disponíveis, podem precisar de diferentes ginásios.

Isto é o que algumas distribuições leves de Linux fazem:

while dmesg -c >> /tmp/dmesg.log; do sleep 0.1; done & tail -f /tmp/dmesg.log

É o fundo do loop while (com &) enquanto se faz a cauda da saída gerada.

Se não se pode escrever para /tmp:

mount -t tmpfs - /tmp 

# or 
mount -t ramfs - /tmp 

# or use /dev/shm instead of /tmp - which is available in newer environments

Se não tiver cauda, pode

cat /tmp/dmesg.log

# or 
dd if=/tmp/dmesg.log 

# or
dd if=/tmp/dmesg.log 2>/dev/null

Ou pode estar num ambiente de caixa ocupada que não tenha dmesg ligado, então apenas:

busybox dmesg -c

Pode também precisar de

busybox sleep

em vez de dormir:

Se não tiver sono:

while dmesg -c; do echo >/dev/null; done

Se não tiver “dmesg”:

while sleep 0.1; do cat -v /proc/kmsg; done

Isto só funciona se nada mais for lido a partir daqui. Pode também ter um /dev/kmsg.

Dica de bónus:

Se não sabe o que tem, e não tem “ls”, apenas:

busybox ls

# or simply:

echo *
3
3
3
2011-05-26 22:01:52 +0000

Talvez possa fazer:

tail -f /var/log/messages
3
3
3
2016-02-04 09:16:00 +0000

Utilizo este pseudónimo em /root/.bashrc;

alias dwatch='watch -n 0.1 "dmesg | tail -n $((LINES-6))"'

que segue o dmesg e ajusta as linhas para qualquer terminal em que é chamado.

0
0
0
2012-12-17 04:37:01 +0000

Sob o actual Ubuntu (estou a usar Ubuntu 12.04 (Pangolin Preciso)),

tail -f /var/log/syslog
6< <( cat /var/log/syslog |grep -F 'kernel: '; sudo cat /proc/kmsg) cat /dev/fd/6

( o comando sudo precisa do privilégio sudo )

Por favor, tente também outro igual: 6\a(dmesg; sudo cat /proc/kmsg) cat /dev/fd/6

0
0
0
2016-01-22 22:49:10 +0000

Utilizei este código para procurar um evento de kernel especial e canalizei-o para um processo de “callback”:

while true ; do dmesg -c ; sleep .1 ; done \
| grep --line-buffered -o $pattern \
| ...
-3
-3
-3
2014-01-15 08:08:27 +0000

Isto pode ser útil:

dmesg | cauda -f -

canaliza a saída de dmesg através da cauda usando o operador - como um atalho para a saída padrão.