-
Notifications
You must be signed in to change notification settings - Fork 392
/
klog_linux.go
117 lines (99 loc) · 3.02 KB
/
klog_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2019 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ulog
import (
"fmt"
"os"
"sync/atomic"
"golang.org/x/sys/unix"
)
// KernelLog is a logger that prints to the kernel syslog buffer.
//
// Default log level is KLogInfo.
//
// If the syslog buffer cannot be written to, KernelLog falls back to Log.
var KernelLog = &KLog{
LogLevel: uintptr(KLogInfo),
}
func init() {
KernelLog.Reinit()
}
// KLog is a logger to the kernel sysloBg buffer.
type KLog struct {
// FD for /dev/kmsg if it was openable.
*os.File
// LogLevel is the LogLevel to print with.
//
// Should only be accessed atomically.
LogLevel uintptr
}
// Reinit reopens the /dev/kmsg file.
func (k *KLog) Reinit() {
f, err := os.OpenFile("/dev/kmsg", os.O_RDWR, 0)
if err == nil {
KernelLog.File = f
}
}
// writeString returns true iff it was able to write the log to /dev/kmsg.
func (k *KLog) writeString(s string) bool {
if k.File == nil {
return false
}
if _, err := k.File.WriteString(fmt.Sprintf("<%d>%s", atomic.LoadUintptr(&k.LogLevel), s)); err != nil {
return false
}
return true
}
// Printf formats according to a format specifier and writes to kernel logging.
func (k *KLog) Printf(format string, v ...interface{}) {
if !k.writeString(fmt.Sprintf(format, v...)) {
Log.Printf(format, v...)
}
}
// Print formats using the default operands for v and writes to kernel logging.
func (k *KLog) Print(v ...interface{}) {
if !k.writeString(fmt.Sprint(v...)) {
Log.Print(v...)
}
}
// KLogLevel are the log levels used by printk.
type KLogLevel uintptr
// These are the log levels used by printk as described in syslog(2).
const (
KLogEmergency KLogLevel = 0
KLogAlert KLogLevel = 1
KLogCritical KLogLevel = 2
KLogError KLogLevel = 3
KLogWarning KLogLevel = 4
KLogNotice KLogLevel = 5
KLogInfo KLogLevel = 6
KLogDebug KLogLevel = 7
)
// SetConsoleLogLevel sets the console level with syslog(2).
//
// After this call, only messages with a level value lower than the one
// specified will be printed to console by the kernel.
func (k *KLog) SetConsoleLogLevel(level KLogLevel) error {
if _, _, err := unix.Syscall(unix.SYS_SYSLOG, unix.SYSLOG_ACTION_CONSOLE_LEVEL, 0, uintptr(level)); err != 0 {
return fmt.Errorf("could not set syslog level to %d: %v", level, err)
}
return nil
}
// SetLogLevel sets the level that Printf and Print log to syslog with.
func (k *KLog) SetLogLevel(level KLogLevel) {
atomic.StoreUintptr(&k.LogLevel, uintptr(level))
}
// ClearLog clears kernel logs back to empty.
func (k *KLog) ClearLog() error {
_, err := unix.Klogctl(unix.SYSLOG_ACTION_CLEAR, nil)
return err
}
// Read reads from the tail of the kernel log.
func (k *KLog) Read(b []byte) (int, error) {
return unix.Klogctl(unix.SYSLOG_ACTION_READ_ALL, b)
}
// ReadClear reads from the tail of the kernel log and clears what was read.
func (k *KLog) ReadClear(b []byte) (int, error) {
return unix.Klogctl(unix.SYSLOG_ACTION_READ_CLEAR, b)
}