kata-containers/tests/error.sh
stevenhorsman dbba6b056b shellcheck: Fix shellcheck SC2148
> Tips depend on target shell and yours is unknown. Add a shebang.

Add
```
#!/usr/bin/env bash
```

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-03-04 09:35:46 +00:00

223 lines
4.3 KiB
Bash

#!/usr/bin/env bash
#
# Copyright (c) 2022-2024 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
# Description: Error handling functions.
# Write specified message to stderr.
stderr()
{
local msg="$*"
echo >&2 "$msg"
}
# Simplified version of die that should be called by functions that
# could fail as part of the normal "die()" code path. Required to
# avoid infinite recursion.
_fatal()
{
local msg="$*"
echo >&2 "FATAL: $msg"
exit 1
}
# Canonicalize the specified path (which must be valid).
resolve_path()
{
local file="${1:-}"
[ -z "$file" ] && _fatal "need file to resolve"
local path
path=$(readlink --canonicalize-existing "$file" || \
_fatal "failed to resolve file '$file'")
echo "$path"
}
show_proc_hierarchy()
{
local pid="${$}"
local details
stderr "process-hierarchy:"
local -i i
for ((i=0; ; i++))
do
local details
local msg
local current=''
[ "${pid}" = "${$}" ] && current=", current='yes'"
details=$(ps --no-headers -p "$pid" -o ppid,cmd)
# The parent PID is always the first column due to the
# format specifier used above.
local ppid=$(echo "$details" | awk '{print $1}')
# But the command part has a variable number of fields
# (since it could contain any number of spaces).
# Hence, delete the first field (PPID) and what
# remains is the entire command line.
local cmd=$(echo "$details" |\
awk '{$1=""; print $0}' |\
sed \
-e 's/^ *//g' \
-e 's/ *$//g')
msg=$(printf " %d: {pid: %d, command: '%s'%s}" \
"${i}" \
"${pid}" \
"${cmd}" \
"${current}")
stderr "$msg"
[ "$pid" = 1 ] && break
pid="$ppid"
done
}
show_stacktrace()
{
local err_line="${1:-}"
local err_func="${2:-}"
local err_path="${3:-}"
[ -z "$err_line" ] && _fatal "need error location line number"
[ -z "$err_func" ] && _fatal "need error location func"
[ -z "$err_path" ] && _fatal "need error location file path"
local line
local func
local file
local -i i
stderr "stacktrace:"
for ((i = 0; ; i++))
do
local result
result=$(caller "$i" || true)
[ -z "$result" ] && break
line=$(echo "$result"|awk '{print $1}')
func=$(echo "$result"|awk '{print $2}')
file=$(echo "$result"|awk '{print $3}')
local path
path=$(resolve_path "$file")
local msg
local current=''
# Add a visual marker showing where the original error was
# detected.
[ "${line}" = "${err_line}" ] && \
[ "${func}" = "${err_func}" ] && \
[ "${path}" = "${err_path}" ] && \
current=", current='yes'"
msg=$(printf " %d: {function: '%s', file: '%s', line: %d%s}\n" \
"${i}" \
"${func}" \
"${path}" \
"${line}" \
"${current}" )
stderr "$msg"
done
}
# Function to be called by die() or a trap/signal handler to dump all
# details of the environment (in YAML format), to help with debugging.
dump_details()
{
set +x
local err_line="${1:-}"
local err_func="${2:-}"
local err_path="${3:-}"
[ -z "$err_line" ] && _fatal "need error location line number"
[ -z "$err_func" ] && _fatal "need error location func"
[ -z "$err_path" ] && _fatal "need error location file path"
# Spacer
stderr
stderr "script:"
stderr " name: '$0'"
stderr " pid: $$"
stderr " directory: '$PWD'"
stderr " details: '$(ls -dlZ "$PWD")'"
stderr "failure:"
stderr " function: '$func'"
stderr " file: '$path'"
stderr " line: $line"
stderr " name: '$0'"
show_stacktrace \
"${err_line}" \
"${err_func}" \
"${err_path}"
show_proc_hierarchy
stderr "time: '$(date -Isec)'"
stderr "runtime-seconds: ${SECONDS}"
stderr "host:"
stderr " name: '$(hostname)'"
stderr " uname: '$(uname -a)'"
stderr "locale:"
locale 2>/dev/null | sed \
-e 's/^/ /g' \
-e 's/=/: '\''/g' \
-e 's/$/'\''/g' \
>&2
stderr "user:"
stderr " uid: {value: $UID, name: '$(getent passwd "$UID"|cut -d: -f1)'}"
stderr " euid: {value: $EUID , name: '$(getent passwd "$EUID"|cut -d: -f1)'}"
stderr " groups: '$(id)'"
stderr "bash:"
stderr " version: '${BASH_VERSION}'"
stderr " version-info: '${BASH_VERSINFO[*]}'"
stderr "environment:"
# Remove bash functions (that can span multiple lines)
env |\
grep -v "^BASH_FUNC" |\
grep -Ei "^[a-z_][a-z0-9_]+=" |\
sort -t '=' -k1 |\
sed \
-e 's/^/ /g' \
-e 's/=/: '\''/' \
-e 's/$/'\''/g' \
>&2
stderr "mounts: |"
mount | sed 's/^/ /g' >&2
stderr "processes: |"
ps -eF | sed 's/^/ /g' >&2
# Spacer
stderr
}