Files
kdumpst/save-dumps.sh
Guilherme G. Piccoli d8815b1cd7 kdump-load/save-dumps: Use shell options to improve reliability
Add hereby "set -uo pipefail", with the goal of improving
reliability (suggested by Emil/@xexaxo). Notice that the
suggestion included "-e", but we make use of this, by checking
non-zero pipes, so instead of refactoring the code to just have
this option, the choice was to not have it.

Also, make use of bash as the shell to execute the tools - after
some analysis, we make use of few bashisms that are a bummer to
change, since a lot of scripts in SteamOS make use of bash and
in general it is a very common shell, let's just go along with it.

Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
2023-03-31 15:34:42 -03:00

148 lines
4.1 KiB
Bash

#!/bin/bash
set -uo pipefail
#
# SPDX-License-Identifier: LGPL-2.1+
#
# Copyright (c) 2021 Valve.
# Maintainer: Guilherme G. Piccoli <gpiccoli@igalia.com>
#
# This is the kdump/pstore log collector; this script prepares the
# collected data and save it in the local disk, in the next successful boot.
#
# Load the necessary external variables, otherwise it'll fail later.
HAVE_CFG_FILES=0
shopt -s nullglob
for cfg in "/usr/share/kdump.d"/*; do
if [ -f "$cfg" ]; then
. "$cfg"
HAVE_CFG_FILES=1
fi
done
shopt -u nullglob
if [ ${HAVE_CFG_FILES} -eq 0 ]; then
logger "kdump: no config files in /usr/share/kdump.d/ - aborting."
exit 1
fi
MAIN_FOLDER="$(cat "${MNT_TMP}")"
rm -f "${MNT_TMP}"
if [ ! -d "${MAIN_FOLDER}" ]; then
logger "kdump: invalid folder (${MAIN_FOLDER}) - aborting..."
exit 1
fi
LOGS_FOUND=0
KDUMP_TMP_FOLDER="${MAIN_FOLDER}/.tmp"
# Use UTC timezone to match kdump collection
CURRENT_TSTAMP=$(date -u +"%Y%m%d%H%M")
# By default, pstore is mounted in this location; if it isn't, we bail-out.
# Notice we currently only support the logs generated by the ramoops backend.
PSTORE_CNT=$(find /sys/fs/pstore/* 2>/dev/null | grep -c ramoops)
if [ "${PSTORE_CNT}" -ne 0 ]; then
PSTORE_FOLDER="${KDUMP_TMP_FOLDER}/pstore"
mkdir -p "${PSTORE_FOLDER}"
LOOP_CNT=0
while [ "${PSTORE_CNT}" -gt 0 ]; do
PSTORE_FILE="$(find /sys/fs/pstore/* | grep ramoops | sort | head -n1)"
SAVED_FILE="${PSTORE_FOLDER}/dmesg-pstore.${CURRENT_TSTAMP}-${LOOP_CNT}"
cat "${PSTORE_FILE}" > "${SAVED_FILE}"
sync "${SAVED_FILE}"
rm -f "${PSTORE_FILE}"
PSTORE_CNT=$((PSTORE_CNT - 1))
LOOP_CNT=$((LOOP_CNT + 1))
done
LOGS_FOUND=${LOOP_CNT}
# Logs should live on <...>/.tmp folder, due to the zip compression.
mv "${PSTORE_FOLDER}"/* "${KDUMP_TMP_FOLDER}/" 2>/dev/null
rm -rf "${PSTORE_FOLDER}"
fi
# Now, we proceed the same way if there are kdump data.
KDUMP_CRASH_FOLDER="${MAIN_FOLDER}/crash"
KDUMP_CNT=$(find "${KDUMP_CRASH_FOLDER}"/* -type d 2>/dev/null | wc -l)
if [ "${KDUMP_CNT}" -ne 0 ]; then
KD_FOLDER="${KDUMP_TMP_FOLDER}/kdump"
mkdir -p "${KD_FOLDER}"
LOOP_CNT=0
while [ "${KDUMP_CNT}" -gt 0 ]; do
CRASH_CURRENT=$(find "${KDUMP_CRASH_FOLDER}"/* -type d 2>/dev/null | head -n1)
# When collecting the vmcore/dmesg during kdump, folder is
# saved with its name == the timestamp of the collection.
CRASH_TSTAMP=$(basename "${CRASH_CURRENT}")
if [ -s "${CRASH_CURRENT}/dmesg.txt" ]; then
SAVED_FILE="${KD_FOLDER}/dmesg-kdump.${CRASH_TSTAMP}"
mv "${CRASH_CURRENT}/dmesg.txt" "${SAVED_FILE}"
sync "${SAVED_FILE}"
fi
# We won't pack vmcores in the zip blob, but let's save
# it in case it was collected as well.
if [ -s "${CRASH_CURRENT}/vmcore.compressed" ]; then
SAVED_FILE="${KDUMP_CRASH_FOLDER}/vmcore.${CRASH_TSTAMP}"
mv "${CRASH_CURRENT}/vmcore.compressed" "${SAVED_FILE}"
sync "${SAVED_FILE}"
fi
rm -rf "${CRASH_CURRENT}"
KDUMP_CNT=$((KDUMP_CNT - 1))
LOOP_CNT=$((LOOP_CNT + 1))
done
LOGS_FOUND=$((LOGS_FOUND + LOOP_CNT))
# Logs should live on .tmp folder, due to the zip compression.
mv "${KD_FOLDER}"/* "${KDUMP_TMP_FOLDER}/" 2>/dev/null
rm -rf "${KD_FOLDER}"
fi
# If we have pstore and/or kdump logs, let's process them...
LOGS_FOLDER="${MAIN_FOLDER}/logs"
if [ ${LOGS_FOUND} -ne 0 ]; then
mkdir -p "${LOGS_FOLDER}"
# First we collect some more info, like DMI data, os-release, etc;
DMI_FNAME="${KDUMP_TMP_FOLDER}/dmidecode.${CURRENT_TSTAMP}"
dmidecode > "${DMI_FNAME}"
BUILD_FNAME="${KDUMP_TMP_FOLDER}/build.${CURRENT_TSTAMP}"
cp "/etc/os-release" "${BUILD_FNAME}"
VERSION_FNAME="${KDUMP_TMP_FOLDER}/version.${CURRENT_TSTAMP}"
uname -r > "${VERSION_FNAME}"
sync "${DMI_FNAME}" "${BUILD_FNAME}" "${VERSION_FNAME}"
# Create the dump compressed pack.
LOG_FNAME="kdump-${CURRENT_TSTAMP}.zip"
LOG_FNAME="${LOGS_FOLDER}/${LOG_FNAME}"
zip -9 -jq "${LOG_FNAME}" "${KDUMP_TMP_FOLDER}"/* 1>/dev/null
sync "${LOG_FNAME}" 2>/dev/null
if [ ! -s "${LOG_FNAME}" ]; then
logger "kdump: couldn't create the compressed log archive"
logger "kdump: check folder \"${KDUMP_TMP_FOLDER}\" for logs"
else
logger "kdump: logs saved in \"${LOGS_FOLDER}\""
fi
fi
rm -rf "${KDUMP_TMP_FOLDER}"