|
Packit |
8ea169 |
#!/usr/bin/python3 -u
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
import sys
|
|
Packit |
8ea169 |
import os
|
|
Packit |
8ea169 |
import locale
|
|
Packit |
8ea169 |
import gettext
|
|
Packit |
8ea169 |
import hashlib
|
|
Packit |
8ea169 |
import re
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GETTEXT_PROGNAME = "abrt"
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
_ = gettext.gettext
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def file_has_string(filename, string):
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
with open(filename, "r") as f:
|
|
Packit |
8ea169 |
for line in f:
|
|
Packit |
8ea169 |
if string in line:
|
|
Packit |
8ea169 |
return True
|
|
Packit |
8ea169 |
except OSError as ex:
|
|
Packit |
8ea169 |
sys.stderr.write("Failed to read file '%s': %s\n"
|
|
Packit |
8ea169 |
% (filename, str(ex)))
|
|
Packit |
8ea169 |
except ValueError as ex:
|
|
Packit |
8ea169 |
sys.stderr.write("Invalid data in file '%s': %s\n"
|
|
Packit |
8ea169 |
% (filename, str(ex)))
|
|
Packit |
8ea169 |
return False
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def tail_with_search(filename, string, maxlen):
|
|
Packit |
8ea169 |
# return empty list on error
|
|
Packit |
8ea169 |
retval = []
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
with open(filename, "r") as f:
|
|
Packit |
8ea169 |
l = []
|
|
Packit |
8ea169 |
for line in f:
|
|
Packit |
8ea169 |
if string in line:
|
|
Packit |
8ea169 |
l.append(line)
|
|
Packit |
8ea169 |
if len(l) > maxlen:
|
|
Packit |
8ea169 |
del l[0]
|
|
Packit |
8ea169 |
retval = l
|
|
Packit |
8ea169 |
except OSError as ex:
|
|
Packit |
8ea169 |
sys.stderr.write("Failed to read file '%s': %s\n"
|
|
Packit |
8ea169 |
% (filename, str(ex)))
|
|
Packit |
8ea169 |
except ValueError as ex:
|
|
Packit |
8ea169 |
sys.stderr.write("Invalid data in file '%s': %s\n"
|
|
Packit |
8ea169 |
% (filename, str(ex)))
|
|
Packit |
8ea169 |
return retval
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def open_or_die(filename, mode):
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
f = open(filename, mode)
|
|
Packit |
8ea169 |
except IOError as e:
|
|
Packit |
8ea169 |
sys.stderr.write(str(e) + "\n")
|
|
Packit |
8ea169 |
sys.exit(1)
|
|
Packit |
8ea169 |
return f
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if __name__ == "__main__":
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
locale.setlocale(locale.LC_ALL, "")
|
|
Packit |
8ea169 |
except locale.Error:
|
|
Packit |
8ea169 |
os.environ['LC_ALL'] = 'C'
|
|
Packit |
8ea169 |
locale.setlocale(locale.LC_ALL, "")
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# Defeat "AttributeError: 'module' object has no attribute 'nl_langinfo'"
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
gettext.bind_textdomain_codeset(GETTEXT_PROGNAME,
|
|
Packit |
8ea169 |
locale.nl_langinfo(locale.CODESET))
|
|
Packit |
8ea169 |
except AttributeError:
|
|
Packit |
8ea169 |
pass
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
gettext.bindtextdomain(GETTEXT_PROGNAME, '/usr/share/locale')
|
|
Packit |
8ea169 |
gettext.textdomain(GETTEXT_PROGNAME)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#
|
|
Packit |
8ea169 |
# So far we only look for Machine Check Exceptions here.
|
|
Packit |
8ea169 |
#
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# See if MCEs were seen
|
|
Packit |
8ea169 |
oops_mce = file_has_string("backtrace", "Machine check events logged");
|
|
Packit |
8ea169 |
vmcore_mce = file_has_string("backtrace", "Machine Check Exception:");
|
|
Packit |
8ea169 |
if not oops_mce and not vmcore_mce:
|
|
Packit |
8ea169 |
sys.exit(0)
|
|
Packit |
8ea169 |
#
|
|
Packit |
8ea169 |
# There was an MCE. IOW: it's not a bug, it's a HW error.
|
|
Packit |
8ea169 |
f = open_or_die("not-reportable", "w")
|
|
Packit |
8ea169 |
f.write(_(
|
|
Packit |
8ea169 |
"The kernel log indicates that hardware errors were detected.\n"
|
|
Packit |
8ea169 |
"This is most likely not a software problem.\n"
|
|
Packit |
8ea169 |
))
|
|
Packit |
8ea169 |
f.close()
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
oops_hash = hashlib.sha1()
|
|
Packit |
8ea169 |
with open("backtrace", "r") as btfile:
|
|
Packit |
8ea169 |
for line in btfile:
|
|
Packit |
8ea169 |
oops_hash.update(line.encode())
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
with open_or_die("uuid", "w") as f:
|
|
Packit |
8ea169 |
f.write(oops_hash.hexdigest())
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
with open_or_die("duphash", "w") as f:
|
|
Packit |
8ea169 |
f.write(oops_hash.hexdigest())
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
res = tail_with_search("dmesg", "Linux version", 1)
|
|
Packit |
8ea169 |
if res:
|
|
Packit |
8ea169 |
kernel = re.sub(r"^.*Linux version ([^ ]+) .*$", r"\1", res[0]);
|
|
Packit |
8ea169 |
with open_or_die("kernel", "w") as krnlfile:
|
|
Packit |
8ea169 |
krnlfile.write(kernel)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
with open_or_die("mce", "w") as f:
|
|
Packit |
8ea169 |
f.write("fatal" if vmcore_mce else "non-fatal")
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# vmcore MCEs already have good backtrace element, nothing more to do
|
|
Packit |
8ea169 |
if vmcore_mce:
|
|
Packit |
8ea169 |
sys.exit(0)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
#
|
|
Packit |
8ea169 |
# Did mcelog logged it to /var/log/mcelog
|
|
Packit |
8ea169 |
# (RHEL6 by default does this)?
|
|
Packit |
8ea169 |
if os.path.exists("/var/log/mcelog"):
|
|
Packit |
8ea169 |
f = open_or_die("backtrace", "w")
|
|
Packit |
8ea169 |
f.write("The kernel log indicates that hardware errors were detected.\n")
|
|
Packit |
8ea169 |
f.write("/var/log/mcelog file may have more information.\n")
|
|
Packit |
8ea169 |
f.write("The last 20 lines of /var/log/mcelog are:\n")
|
|
Packit |
8ea169 |
f.write("=========================================\n")
|
|
Packit |
8ea169 |
#tail -n20 /var/log/mcelog 2>&1
|
|
Packit |
8ea169 |
l = tail_with_search("/var/log/mcelog", "", 20)
|
|
Packit |
8ea169 |
for line in l:
|
|
Packit |
8ea169 |
f.write(line)
|
|
Packit |
8ea169 |
f.close()
|
|
Packit |
8ea169 |
sys.exit(0)
|
|
Packit |
8ea169 |
#
|
|
Packit |
8ea169 |
# On RHEL7, mcelog is run so that its output ends up in syslog.
|
|
Packit |
8ea169 |
# Do we see that?
|
|
Packit |
8ea169 |
if file_has_string("/var/log/messages", "mcelog: Hardware event"):
|
|
Packit |
8ea169 |
f = open_or_die("backtrace", "w")
|
|
Packit |
8ea169 |
f.write("The kernel log indicates that hardware errors were detected.\n")
|
|
Packit |
8ea169 |
f.write("System log may have more information.\n")
|
|
Packit |
8ea169 |
f.write("The last 20 mcelog lines of system log are:\n")
|
|
Packit |
8ea169 |
f.write("==========================================\n")
|
|
Packit |
8ea169 |
#grep -Fi 'mcelog:' /var/log/messages | tail -n20 2>&1
|
|
Packit |
8ea169 |
l = tail_with_search("/var/log/messages", "mcelog:", 20)
|
|
Packit |
8ea169 |
for line in l:
|
|
Packit |
8ea169 |
f.write(line)
|
|
Packit |
8ea169 |
f.close()
|
|
Packit |
8ea169 |
sys.exit(0)
|
|
Packit |
8ea169 |
#
|
|
Packit |
8ea169 |
# Apparently, there is no running mcelog daemon!
|
|
Packit |
8ea169 |
# Let user know that he needs one.
|
|
Packit |
8ea169 |
f = open_or_die("backtrace", "w")
|
|
Packit |
8ea169 |
f.write("The kernel log indicates that hardware errors were detected.\n")
|
|
Packit |
8ea169 |
f.write("The data was saved by kernel for processing by the mcelog tool.\n")
|
|
Packit |
8ea169 |
f.write("However, neither /var/log/mcelog nor system log contain mcelog messages.\n")
|
|
Packit |
8ea169 |
f.write("Most likely reason is that mcelog is not installed or not configured\n")
|
|
Packit |
8ea169 |
f.write("to be started during boot.\n")
|
|
Packit |
8ea169 |
f.write("Without this tool running, the binary data saved by kernel\n")
|
|
Packit |
8ea169 |
f.write("is of limited usefulness.\n")
|
|
Packit |
8ea169 |
f.write("(You can save this data anyway by running 'cat </dev/mcelog >FILE').\n")
|
|
Packit |
8ea169 |
f.write("The recommended course of action is to install mcelog.\n")
|
|
Packit |
8ea169 |
f.write("If another hardware error would occur, a user-readable description\n")
|
|
Packit |
8ea169 |
f.write("of it will be saved in system log or /var/log/mcelog.\n")
|
|
Packit |
8ea169 |
f.close()
|