| #!/bin/bash |
| # This script sets up the environment for kernel crash dump debugging. |
| |
| set -eu |
| set -o pipefail |
| |
| |
| readonly PROG_NAME=$(basename "$0") |
| readonly REPORT_TARBALL_DIR="/sos" |
| readonly REPORT_DIR="sos" |
| CRASH_COMMAND="" |
| VMLINUX_PATH="" |
| |
| # |
| # usage <exit_code> |
| # |
| # Print usage and exit. |
| # |
| usage() { |
| local exit_code="${1}" |
| |
| cat <<EOF |
| Usage: |
| ${PROG_NAME} [-s <sos>] [-c <crash_command>] [-p <vmlinux_path>] |
| -s, --sos The filename of the sosreport tarball. |
| -c, --crash_command The crash command to run. Will open a shell for interactive debugging after running this command. |
| -p, --vmlinux_path The gsutil path to the matching vmlinux. If not set, the vmlinux will be fetched from gs://cos-tools. |
| |
| Examples: |
| $ ${PROG_NAME} --sos sosreport-kdump-next-20190130220549.tar.xz |
| $ ${PROG_NAME} -s sosreport-kdump-next-20190130220549.tar.xz -c bt -p gs://cos-tools/15978.0.0/vmlinux |
| |
| Note: |
| Expecting the sosreport tarball to be located at REPORT_TARBALL_DIR. |
| EOF |
| exit "${exit_code}" |
| } |
| |
| |
| # |
| # parse_args <args...> |
| # |
| # Parse command line arguments. |
| # |
| parse_args() { |
| local args |
| |
| if ! args=$(getopt \ |
| --options "c: s: p: n" \ |
| --longoptions "crash_command: sos: vmlinux_path:" \ |
| -- "$@"); then |
| usage 1 |
| fi |
| eval set -- "${args}" |
| |
| while :; do |
| arg="${1}" |
| shift |
| case "${arg}" in |
| -c|--crash_command) CRASH_COMMAND="${1}"; shift ;; |
| -s|--sos) REPORT_TARBALL="${1}"; shift ;; |
| -p|--vmlinux_path) VMLINUX_PATH="${1}"; shift ;; |
| --) break ;; |
| *) echo "internal error parsing arguments!"; usage 1 ;; |
| esac |
| done |
| } |
| |
| |
| # |
| # setup |
| # |
| # Setup the work directory for debugging, containing: |
| # 1. Uncompressed sosreport tarball. |
| # 2. vmlinux for the COS kernel. |
| # 3. Latest kernel crash dump. |
| # |
| setup() { |
| local sosreport_dir |
| local buildnumber |
| |
| # We want all data get automatically removed after container exit. |
| WORKDIR=$(mktemp -d) |
| cd "${WORKDIR}" |
| |
| # Uncompress sosreport tarball, and rename the folder into $REPORT_TARBALL |
| echo "Uncompressing sosreport tarball." |
| tar -xf "${REPORT_TARBALL_DIR}/${REPORT_TARBALL}" |
| sosreport_dir=$(find ./sosreport-* -maxdepth 0 | sed -n 1p) |
| mv "${sosreport_dir}" "${REPORT_DIR}" |
| |
| # Copy the latest kernel crash dump to the workdir for easy access |
| cp "${REPORT_DIR}/var/kdump" . |
| |
| # If VMLINUX_PATH is not set, fetch the vmlinux from gs://cos-tools |
| if [[ -z "${VMLINUX_PATH}" ]]; then |
| echo "--vmlinux_path not set, fetching vmlinux from gs://cos-tools" |
| buildnumber=$(grep BUILD_ID "${REPORT_DIR}/etc/os-release" | cut -d "=" -f 2) |
| VMLINUX_PATH="gs://cos-tools/${buildnumber}/vmlinux" |
| fi |
| |
| echo "Downloading ${VMLINUX_PATH}." |
| gsutil -q cp "${VMLINUX_PATH}" . |
| } |
| |
| |
| # |
| # run |
| # |
| # This steps will start inspect the kernel crash dump: |
| # If CRASH_COMMAND is set, this step will execute the given command. |
| # Otherwise, this step will open a shell for interactive debugging. |
| # |
| run() { |
| if [[ -n "${CRASH_COMMAND}" ]]; then |
| echo "Running crash command: ${CRASH_COMMAND}." |
| echo -e "${CRASH_COMMAND}\nq" | crash vmlinux kdump |
| fi |
| |
| # Give control to user, if no debugging command is specified. |
| exec /bin/bash |
| } |
| |
| |
| main() { |
| parse_args "$@" |
| |
| setup |
| |
| run |
| } |
| |
| main "$@" |