1#!/usr/bin/env bash 2# We don't want to tell kernel to include %e or %E since these 3# can include whitespaces or other funny characters, and working 4# with those on the cmdline would be a nightmare. Use procfs for 5# the remaining pieces we want to gather: 6# |$rootdir/scripts/core-collector.sh %P %s %t $output_dir 7 8get_rlimit() { 9 local limit 10 11 while read -ra limit; do 12 [[ ${limit[1]} == core ]] && echo "${limit[4]}" # soft 13 done < "/proc/$core_pid/limits" 14} 15 16core_meta() { 17 jq . <<- CORE 18 { 19 "$exe_comm": { 20 "ts": "$core_time", 21 "size": "$core_size bytes", 22 "PID": $core_pid, 23 "signal": "$core_sig ($core_sig_name)", 24 "path": "$exe_path", 25 "statm": "$statm" 26 } 27 } 28 CORE 29} 30 31bt() { hash gdb && gdb -batch -ex "thread apply all bt full" "$1" "$2" 2>&1; } 32 33stderr() { 34 exec 2> "$core.stderr.txt" 35 set -x 36} 37 38args+=(core_pid) 39args+=(core_sig) 40args+=(core_ts) 41args+=(output_dir) 42 43read -r "${args[@]}" <<< "$*" 44 45exe_path=$(readlink -f "/proc/$core_pid/exe") 46exe_comm=$(< "/proc/$core_pid/comm") 47statm=$(< "/proc/$core_pid/statm") 48core_time=$(date -d@"$core_ts") 49core_sig_name=$(kill -l "$core_sig") 50 51core=$output_dir/${exe_path##*/}_$core_pid.core 52stderr 53 54# RLIMIT_CORE is not enforced when core is piped to us. To make 55# sure we won't attempt to overload underlying storage, copy 56# only the reasonable amount of bytes (systemd defaults to 2G 57# so let's follow that). But first, check limits of terminating 58# process to see if we need to make any adjustments. 59max_core=$((1024 * 1024 * 1024 * 2)) 60 61rlimit=$(get_rlimit) 62if [[ $rlimit == unlimited ]] || ((rlimit > max_core)); then 63 rlimit=$max_core 64fi 65 66# Nothing to do 67((rlimit == 0)) && exit 0 68 69# Clear path for lz 70rm -f "$core"{,.{bin,bt,gz,json}} 71 72# Slurp the core 73head -c "$rlimit" <&0 > "$core" 74core_size=$(wc -c < "$core") 75 76# Compress it 77gzip -c "$core" > "$core.gz" 78 79# Save the binary 80cp "$exe_path" "$core.bin" 81 82# Save the backtrace 83bt "$exe_path" "$core" > "$core.bt.txt" 84 85# Save the metadata of the core 86core_meta > "$core.json" 87 88# Nuke the original core 89rm "$core" 90