152 lines
4.7 KiB
Bash
Executable File
152 lines
4.7 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# SPDX-License-Identifier: LGPL-2.1+
|
|
#
|
|
# Copyright (c) 2021 Valve.
|
|
#
|
|
# This is the SteamOS kdump/pstore log collector and submitter; this script
|
|
# prepares the pstore/kdump collected data and submit it to the services that
|
|
# handle support at Valve. It considers pstore as a first alternative, if no
|
|
# logs found (or if pstore is not mounted for some reason), tries to check
|
|
# if kdump logs are present.
|
|
#
|
|
|
|
# We do some validation to be sure KDUMP_MNT pointed path is valid...
|
|
# That and having a valid /etc/default/kdump are essential conditions.
|
|
if [ ! -f "/etc/default/kdump" ]; then
|
|
logger "kdump-steamos: /etc/default/kdump not present - aborting..."
|
|
exit 0
|
|
fi
|
|
|
|
. /etc/default/kdump
|
|
|
|
KDUMP_MAIN_FOLDER="$(cat "${KDUMP_MNT}")"
|
|
rm -f "${KDUMP_MNT}"
|
|
|
|
if [ ! -d "${KDUMP_MAIN_FOLDER}" ]; then
|
|
logger "kdump-steamos: invalid folder (${KDUMP_MAIN_FOLDER}) - aborting..."
|
|
exit 0
|
|
fi
|
|
|
|
LOGS_FOUND=0
|
|
KDUMP_LOGS_FOLDER="${KDUMP_MAIN_FOLDER}/logs"
|
|
|
|
# Use UTC timezone to match kdump collection
|
|
CURRENT_TSTAMP=$(date -u +"%Y%m%d%H%M")
|
|
|
|
# We assume pstore is mounted by default, in this location;
|
|
# if not, we get a 0 and don't loop.
|
|
PSTORE_CNT=$(find /sys/fs/pstore/* 2>/dev/null | grep -c ramoops)
|
|
if [ "${PSTORE_CNT}" -ne 0 ]; then
|
|
|
|
# Dump the pstore logs in the <...>/kdump/logs/pstore subfolder.
|
|
PSTORE_FOLDER="${KDUMP_LOGS_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 logs/ folder (no subfolders), due to the zip file
|
|
mv "${PSTORE_FOLDER}"/* "${KDUMP_LOGS_FOLDER}/" 2>/dev/null
|
|
|
|
# Enter the else block in case we don't have pstore logs - maybe we
|
|
# have kdump logs then.
|
|
else
|
|
KDUMP_CRASH_FOLDER="${KDUMP_MAIN_FOLDER}/crash"
|
|
KDUMP_CNT=$(find "${KDUMP_CRASH_FOLDER}"/* -type d 2>/dev/null | wc -l)
|
|
|
|
if [ "${KDUMP_CNT}" -ne 0 ]; then
|
|
# Dump the kdump logs in the <...>/kdump/logs/kdump subfolder.
|
|
KD_FOLDER="${KDUMP_LOGS_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)
|
|
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 don't care about submitting a vmcore, but let's save it if such file exists.
|
|
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 logs/ folder (no subfolders), due to the zip file
|
|
mv "${KD_FOLDER}"/* "${KDUMP_LOGS_FOLDER}/" 2>/dev/null
|
|
fi
|
|
|
|
fi
|
|
|
|
# If we have pstore and/or kdump logs, let's process them in order to submit...
|
|
if [ ${LOGS_FOUND} -ne 0 ]; then
|
|
|
|
PNAME="$(dmidecode -s system-product-name)"
|
|
if [ "${PNAME}" = "Jupiter" ]; then
|
|
SN="$(dmidecode -s system-serial-number)"
|
|
else
|
|
SN=0
|
|
fi
|
|
|
|
STEAM_ACCOUNT=0
|
|
if [ -s "${LOGINVDF}" ]; then
|
|
# The following awk command was borrowed from:
|
|
# https://unix.stackexchange.com/a/663959
|
|
NUMREG=$(grep -c AccountName "${LOGINVDF}")
|
|
IDX=1
|
|
while [ ${IDX} -le "${NUMREG}" ]; do
|
|
MR=$(awk -v n=${IDX} -v RS='}' 'NR==n{gsub(/.*\{\n|\n$/,""); print}' "${LOGINVDF}" | grep "MostRecent" | cut -f4 -d\")
|
|
if [ "$MR" -ne 1 ]; then
|
|
IDX=$((IDX + 1))
|
|
continue
|
|
fi
|
|
|
|
STEAM_ACCOUNT=$(awk -v n=${IDX} -v RS='}' 'NR==n{gsub(/.*\{\n|\n$/,""); print}' "${LOGINVDF}" | grep "AccountName" | cut -f4 -d\")
|
|
break
|
|
done
|
|
fi
|
|
|
|
# Here we collect some more info, like DMI data, os-release, etc;
|
|
# ToDo: Add Steam application / Proton / Games logs collection...
|
|
dmidecode > "${KDUMP_LOGS_FOLDER}/dmidecode.${CURRENT_TSTAMP}"
|
|
grep "BUILD_ID" "/etc/os-release" | cut -f2 -d\= > "${KDUMP_LOGS_FOLDER}/build.${CURRENT_TSTAMP}"
|
|
uname -r > "${KDUMP_LOGS_FOLDER}/version.${CURRENT_TSTAMP}"
|
|
|
|
# Create the dump compressed pack.
|
|
LOG_FNAME="steamos-${SN}-${STEAM_ACCOUNT}.${CURRENT_TSTAMP}.zip"
|
|
LOG_FNAME="${KDUMP_MAIN_FOLDER}/${LOG_FNAME}"
|
|
|
|
zip -9 -jq "${LOG_FNAME}" ${KDUMP_LOGS_FOLDER}/* 1>/dev/null 2>&1
|
|
sync "${LOG_FNAME}"
|
|
rm -rf "${KDUMP_LOGS_FOLDER}"
|
|
|
|
# TODO: implement a log submission mechanism, in order to send the zip file
|
|
# to Valve servers through an API.
|
|
fi
|