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>
148 lines
4.1 KiB
Bash
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}"
|