]>
Commit | Line | Data |
---|---|---|
e103615b AŻ |
1 | #!/bin/sh |
2 | # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- | |
3 | # ex: ts=8 sw=4 et filetype=sh | |
4 | # | |
5 | # logging faciality module for dracut both at build- and boot-time | |
6 | # | |
7 | # Copyright 2010 Amadeusz Żołnowski <aidecoe@aidecoe.name> | |
8 | # | |
9 | # This program is free software; you can redistribute it and/or modify | |
10 | # it under the terms of the GNU General Public License as published by | |
11 | # the Free Software Foundation; either version 2 of the License, or | |
12 | # (at your option) any later version. | |
13 | # | |
14 | # This program is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | # GNU General Public License for more details. | |
18 | # | |
19 | # You should have received a copy of the GNU General Public License | |
20 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ||
23 | __DRACUT_LOGGER__=1 | |
24 | ||
25 | ||
26 | ## @brief Logging facility module for Dracut both at build- and boot-time. | |
27 | # | |
28 | # @section intro Introduction | |
29 | # | |
30 | # The logger takes a bit from Log4j philosophy. There are defined 6 logging | |
31 | # levels: | |
32 | # - TRACE (6) | |
33 | # The TRACE Level designates finer-grained informational events than the | |
34 | # DEBUG. | |
35 | # - DEBUG (5) | |
36 | # The DEBUG Level designates fine-grained informational events that are most | |
37 | # useful to debug an application. | |
38 | # - INFO (4) | |
39 | # The INFO level designates informational messages that highlight the | |
40 | # progress of the application at coarse-grained level. | |
41 | # - WARN (3) | |
42 | # The WARN level designates potentially harmful situations. | |
43 | # - ERROR (2) | |
44 | # The ERROR level designates error events that might still allow the | |
45 | # application to continue running. | |
46 | # - FATAL (1) | |
47 | # The FATAL level designates very severe error events that will presumably | |
48 | # lead the application to abort. | |
49 | # Descriptions are borrowed from Log4j documentation: | |
50 | # http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html | |
51 | # | |
52 | # @section usage Usage | |
53 | # | |
54 | # First of all you have to start with dlog_init() function which initializes | |
55 | # required variables. Don't call any other logging function before that one! | |
56 | # If you're ready with this, you can use following functions which corresponds | |
57 | # clearly to levels listed in @ref intro Introduction. Here they are: | |
58 | # - dtrace() | |
59 | # - ddebug() | |
60 | # - dinfo() | |
61 | # - dwarn() | |
62 | # - derror() | |
63 | # - dfatal() | |
64 | # They take all arguments given as a single message to be logged. See dlog() | |
65 | # function for details how it works. Note that you shouldn't use dlog() by | |
66 | # yourself. It's wrapped with above functions. | |
67 | # | |
68 | # @see dlog_init() dlog() | |
69 | # | |
70 | # @section conf Configuration | |
71 | # | |
72 | # Logging is controlled by following global variables: | |
73 | # - @var stdloglvl - logging level to standard error (console output) | |
74 | # - @var sysloglvl - logging level to syslog (by logger command) | |
75 | # - @var fileloglvl - logging level to file | |
76 | # - @var kmsgloglvl - logging level to /dev/kmsg (only for boot-time) | |
77 | # - @var logfile - log file which is used when @var fileloglvl is higher | |
78 | # than 0 | |
9ebc5110 AŻ |
79 | # and two global variables: @var maxloglvl and @var syslogfacility which <b>must |
80 | # not</b> be overwritten. Both are set by dlog_init(). @var maxloglvl holds | |
81 | # maximum logging level of those three and indicates that dlog_init() was run. | |
82 | # @var syslogfacility is set either to 'user' (when building initramfs) or | |
83 | # 'daemon' (when booting). | |
e103615b AŻ |
84 | # |
85 | # Logging level set by the variable means that messages from this logging level | |
86 | # and above (FATAL is the highest) will be shown. Logging levels may be set | |
87 | # independently for each destination (stderr, syslog, file, kmsg). | |
88 | # | |
89 | # @see dlog_init() | |
90 | ||
91 | ||
92 | ## @brief Initializes Dracut Logger. | |
93 | # | |
94 | # @retval 1 if something has gone wrong | |
95 | # @retval 0 on success. | |
96 | # | |
97 | # @note This function need to be called before any other from this file. | |
98 | # | |
99 | # If any of the variables is not set, this function set it to default: | |
100 | # - @var stdloglvl = 4 (info) | |
101 | # - @var sysloglvl = 0 (no logging) | |
102 | # - @var fileloglvl is set to 4 when @var logfile is set too, otherwise it's | |
103 | # - @var kmsgloglvl = 0 (no logging) | |
104 | # set to 0 | |
105 | # | |
9ebc5110 AŻ |
106 | # @warning Function sets global variables @var maxloglvl and @syslogfacility. |
107 | # See file doc comment for details. | |
e103615b | 108 | dlog_init() { |
e45ffb5d | 109 | local __oldumask |
e103615b | 110 | local ret=0; local errmsg |
e103615b AŻ |
111 | [ -z "$stdloglvl" ] && stdloglvl=4 |
112 | [ -z "$sysloglvl" ] && sysloglvl=0 | |
113 | [ -z "$kmsgloglvl" ] && kmsgloglvl=0 | |
3cd98a60 HH |
114 | # Skip initialization if it's already done. |
115 | [ -n "$maxloglvl" ] && return 0 | |
e103615b AŻ |
116 | |
117 | if [ -z "$fileloglvl" ]; then | |
118 | [ -w "$logfile" ] && fileloglvl=4 || fileloglvl=0 | |
119 | elif [ $fileloglvl -gt 0 ]; then | |
e45ffb5d HH |
120 | __oldumask=$(umask) |
121 | umask 0377 | |
e103615b | 122 | ! [ -e "$logfile" ] && >"$logfile" |
e45ffb5d | 123 | umask $__oldumask |
e103615b AŻ |
124 | if [ -w "$logfile" -a -f "$logfile" ]; then |
125 | # Mark new run in the log file | |
126 | echo >>"$logfile" | |
127 | if command -v date >/dev/null; then | |
128 | echo "=== $(date) ===" >>"$logfile" | |
129 | else | |
130 | echo "===============================================" >>"$logfile" | |
131 | fi | |
132 | echo >>"$logfile" | |
133 | else | |
134 | # We cannot log to file, so turn this facility off. | |
135 | fileloglvl=0 | |
136 | ret=1 | |
137 | errmsg="'$logfile' is not a writable file" | |
138 | fi | |
139 | fi | |
140 | ||
141 | if [ $sysloglvl -gt 0 ]; then | |
d60b71e8 | 142 | if ! [ -S /dev/log -a -w /dev/log ] || ! command -v logger >/dev/null |
e103615b AŻ |
143 | then |
144 | # We cannot log to syslog, so turn this facility off. | |
145 | sysloglvl=0 | |
146 | ret=1 | |
d60b71e8 | 147 | errmsg="No '/dev/log' or 'logger' included for syslog logging" |
e103615b AŻ |
148 | fi |
149 | fi | |
150 | ||
9ebc5110 AŻ |
151 | if [ $sysloglvl -gt 0 -o $kmsgloglvl -gt 0 ]; then |
152 | if [ -n "$dracutbasedir" ]; then | |
153 | readonly syslogfacility=user | |
154 | else | |
155 | readonly syslogfacility=daemon | |
156 | fi | |
157 | export syslogfacility | |
158 | fi | |
159 | ||
46265a9d AŻ |
160 | local lvl; local maxloglvl_l=0 |
161 | for lvl in $stdloglvl $sysloglvl $fileloglvl $kmsgloglvl; do | |
162 | [ $lvl -gt $maxloglvl_l ] && maxloglvl_l=$lvl | |
e103615b | 163 | done |
46265a9d AŻ |
164 | readonly maxloglvl=$maxloglvl_l |
165 | export maxloglvl | |
e103615b AŻ |
166 | |
167 | [ -n "$errmsg" ] && derror "$errmsg" | |
168 | ||
169 | return $ret | |
170 | } | |
171 | ||
172 | ## @brief Converts numeric logging level to the first letter of level name. | |
173 | # | |
174 | # @param lvl Numeric logging level in range from 1 to 6. | |
175 | # @retval 1 if @a lvl is out of range. | |
176 | # @retval 0 if @a lvl is correct. | |
177 | # @result Echoes first letter of level name. | |
178 | _lvl2char() { | |
179 | case "$1" in | |
180 | 1) echo F;; | |
181 | 2) echo E;; | |
182 | 3) echo W;; | |
183 | 4) echo I;; | |
184 | 5) echo D;; | |
185 | 6) echo T;; | |
186 | *) return 1;; | |
187 | esac | |
188 | } | |
189 | ||
190 | ## @brief Converts numeric level to logger priority defined by POSIX.2. | |
191 | # | |
192 | # @param lvl Numeric logging level in range from 1 to 6. | |
193 | # @retval 1 if @a lvl is out of range. | |
194 | # @retval 0 if @a lvl is correct. | |
195 | # @result Echoes logger priority. | |
9ebc5110 AŻ |
196 | _lvl2syspri() { |
197 | printf $syslogfacility. | |
e103615b AŻ |
198 | case "$1" in |
199 | 1) echo crit;; | |
200 | 2) echo error;; | |
201 | 3) echo warning;; | |
202 | 4) echo info;; | |
203 | 5) echo debug;; | |
204 | 6) echo debug;; | |
205 | *) return 1;; | |
206 | esac | |
207 | } | |
208 | ||
9ebc5110 | 209 | ## @brief Converts dracut-logger numeric level to syslog log level |
510ef3af AŻ |
210 | # |
211 | # @param lvl Numeric logging level in range from 1 to 6. | |
212 | # @retval 1 if @a lvl is out of range. | |
213 | # @retval 0 if @a lvl is correct. | |
214 | # @result Echoes kernel console numeric log level | |
215 | # | |
216 | # Conversion is done as follows: | |
217 | # | |
218 | # <tt> | |
9ebc5110 AŻ |
219 | # FATAL(1) -> LOG_EMERG (0) |
220 | # none -> LOG_ALERT (1) | |
221 | # none -> LOG_CRIT (2) | |
222 | # ERROR(2) -> LOG_ERR (3) | |
223 | # WARN(3) -> LOG_WARNING (4) | |
224 | # none -> LOG_NOTICE (5) | |
225 | # INFO(4) -> LOG_INFO (6) | |
226 | # DEBUG(5) -> LOG_DEBUG (7) | |
510ef3af AŻ |
227 | # TRACE(6) / |
228 | # </tt> | |
9ebc5110 AŻ |
229 | # |
230 | # @see /usr/include/sys/syslog.h | |
231 | _dlvl2syslvl() { | |
232 | local lvl | |
233 | ||
510ef3af | 234 | case "$1" in |
9ebc5110 AŻ |
235 | 1) lvl=0;; |
236 | 2) lvl=3;; | |
237 | 3) lvl=4;; | |
238 | 4) lvl=6;; | |
239 | 5) lvl=7;; | |
240 | 6) lvl=7;; | |
510ef3af AŻ |
241 | *) return 1;; |
242 | esac | |
9ebc5110 AŻ |
243 | |
244 | [ "$syslogfacility" = user ] && echo $((8+$lvl)) || echo $((24+$lvl)) | |
510ef3af AŻ |
245 | } |
246 | ||
e103615b AŻ |
247 | ## @brief Prints to stderr and/or writes to file, to syslog and/or /dev/kmsg |
248 | # given message with given level (priority). | |
249 | # | |
250 | # @param lvl Numeric logging level. | |
251 | # @param msg Message. | |
252 | # @retval 0 It's always returned, even if logging failed. | |
253 | # | |
254 | # @note This function is not supposed to be called manually. Please use | |
255 | # dtrace(), ddebug(), or others instead which wrap this one. | |
256 | # | |
257 | # This is core logging function which logs given message to standard error, file | |
258 | # and/or syslog (with POSIX shell command <tt>logger</tt>) and/or to /dev/kmsg. | |
259 | # The format is following: | |
260 | # | |
261 | # <tt>X: some message</tt> | |
262 | # | |
263 | # where @c X is the first letter of logging level. See module description for | |
264 | # details on that. | |
265 | # | |
266 | # Message to syslog is sent with tag @c dracut. Priorities are mapped as | |
267 | # following: | |
268 | # - @c FATAL to @c crit | |
269 | # - @c ERROR to @c error | |
270 | # - @c WARN to @c warning | |
271 | # - @c INFO to @c info | |
272 | # - @c DEBUG and @c TRACE both to @c debug | |
200c7fd4 | 273 | _do_dlog() { |
e103615b AŻ |
274 | local lvl="$1"; shift |
275 | local lvlc=$(_lvl2char "$lvl") || return 0 | |
e103615b AŻ |
276 | local msg="$lvlc: $*" |
277 | ||
278 | [ $lvl -le $stdloglvl ] && echo "$msg" >&2 | |
279 | if [ $lvl -le $sysloglvl ]; then | |
9ebc5110 | 280 | logger -t "dracut[$$]" -p $(_lvl2syspri $lvl) "$msg" |
e103615b AŻ |
281 | fi |
282 | if [ $lvl -le $fileloglvl -a -w "$logfile" -a -f "$logfile" ]; then | |
283 | echo "$msg" >>"$logfile" | |
284 | fi | |
510ef3af | 285 | [ $lvl -le $kmsgloglvl ] && \ |
9ebc5110 | 286 | echo "<$(_dlvl2syslvl $lvl)>dracut[$$] $msg" >/dev/kmsg |
e103615b AŻ |
287 | } |
288 | ||
200c7fd4 HH |
289 | ## @brief Internal helper function for _do_dlog() |
290 | # | |
291 | # @param lvl Numeric logging level. | |
292 | # @param msg Message. | |
293 | # @retval 0 It's always returned, even if logging failed. | |
294 | # | |
295 | # @note This function is not supposed to be called manually. Please use | |
296 | # dtrace(), ddebug(), or others instead which wrap this one. | |
297 | # | |
298 | # This function calls _do_dlog() either with parameter msg, or if | |
299 | # none is given, it will read standard input and will use every line as | |
300 | # a message. | |
301 | # | |
302 | # This enables: | |
303 | # dwarn "This is a warning" | |
304 | # echo "This is a warning" | dwarn | |
305 | dlog() { | |
69063507 HH |
306 | [ -z "$maxloglvl" ] && return 0 |
307 | [ $1 -le $maxloglvl ] || return 0 | |
308 | ||
200c7fd4 HH |
309 | if [ $# -gt 1 ]; then |
310 | _do_dlog "$@" | |
311 | else | |
312 | while read line; do | |
313 | _do_dlog "$1" "$line" | |
314 | done | |
315 | fi | |
200c7fd4 HH |
316 | } |
317 | ||
e103615b AŻ |
318 | ## @brief Logs message at TRACE level (6) |
319 | # | |
320 | # @param msg Message. | |
321 | # @retval 0 It's always returned, even if logging failed. | |
322 | dtrace() { | |
1e64e493 | 323 | set +x |
200c7fd4 | 324 | dlog 6 "$@" |
44cef0d5 | 325 | [ -n "$debug" ] && set -x || : |
e103615b AŻ |
326 | } |
327 | ||
328 | ## @brief Logs message at DEBUG level (5) | |
329 | # | |
330 | # @param msg Message. | |
331 | # @retval 0 It's always returned, even if logging failed. | |
332 | ddebug() { | |
1e64e493 | 333 | set +x |
200c7fd4 | 334 | dlog 5 "$@" |
44cef0d5 | 335 | [ -n "$debug" ] && set -x || : |
e103615b AŻ |
336 | } |
337 | ||
338 | ## @brief Logs message at INFO level (4) | |
339 | # | |
340 | # @param msg Message. | |
341 | # @retval 0 It's always returned, even if logging failed. | |
342 | dinfo() { | |
1e64e493 | 343 | set +x |
200c7fd4 | 344 | dlog 4 "$@" |
44cef0d5 | 345 | [ -n "$debug" ] && set -x || : |
e103615b AŻ |
346 | } |
347 | ||
348 | ## @brief Logs message at WARN level (3) | |
349 | # | |
350 | # @param msg Message. | |
351 | # @retval 0 It's always returned, even if logging failed. | |
352 | dwarn() { | |
1e64e493 | 353 | set +x |
200c7fd4 | 354 | dlog 3 "$@" |
44cef0d5 | 355 | [ -n "$debug" ] && set -x || : |
e103615b AŻ |
356 | } |
357 | ||
358 | ## @brief It's an alias to dwarn() function. | |
359 | # | |
360 | # @param msg Message. | |
361 | # @retval 0 It's always returned, even if logging failed. | |
362 | dwarning() { | |
1e64e493 | 363 | set +x |
200c7fd4 | 364 | dwarn "$@" |
44cef0d5 | 365 | [ -n "$debug" ] && set -x || : |
e103615b AŻ |
366 | } |
367 | ||
368 | ## @brief Logs message at ERROR level (2) | |
369 | # | |
370 | # @param msg Message. | |
371 | # @retval 0 It's always returned, even if logging failed. | |
372 | derror() { | |
1e64e493 | 373 | set +x |
200c7fd4 | 374 | dlog 2 "$@" |
44cef0d5 | 375 | [ -n "$debug" ] && set -x || : |
e103615b AŻ |
376 | } |
377 | ||
378 | ## @brief Logs message at FATAL level (1) | |
379 | # | |
380 | # @param msg Message. | |
381 | # @retval 0 It's always returned, even if logging failed. | |
382 | dfatal() { | |
1e64e493 | 383 | set +x |
200c7fd4 | 384 | dlog 1 "$@" |
44cef0d5 | 385 | [ -n "$debug" ] && set -x || : |
e103615b | 386 | } |