Last active
August 29, 2015 14:11
-
-
Save leandro-lucarella-sociomantic/f36a77d49dd3515f207c to your computer and use it in GitHub Desktop.
A better core dump file writer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -e | |
# Comment out for debugging | |
#exec 2> /tmp/core.log | |
#echo "$@" >&2 | |
#set -x | |
keep=0 | |
dest=cwd | |
pid= | |
uid= | |
gid= | |
time= | |
exe_name= | |
soft_link=0 | |
hard_link=0 | |
usage() | |
{ | |
cat <<EOT | |
Usage: $0 [OPTIONS] PID | |
Write core files received via stdin to DEST, using the pattern: | |
exe-YYYYmmddHHMMSS.PID.core | |
This script is suitable (and written for) usage as kernel.core_pattern pipe, | |
the most simple usage example is: | |
sysctl kernel.core_pattern="|/path/to/script %p" | |
Arguments: | |
PID PID of the process which core is being dumped | |
Options: | |
-h print this help menssage and exits | |
-k MAX keep a maximum of MAX core files (0 means infinite) | |
Default: $keep | |
-d DEST put the core files in DEST. DEST must be an absolute path or, | |
alternatively, it should start with the special values "cwd" or | |
"exe". If "cwd" is used, then the core file will be written | |
relatively to the the process current working directory (as | |
presented in /proc/PID/cwd), if "exe" is used, the executable | |
directory will be used instead (as the target of /proc/PID/exe | |
shows). So you can use something like cwd/core-files for | |
example to write to a subdirectory in the current working | |
directory. | |
Default: $dest | |
-u UID user ID of the process owner | |
Default: obtained from /proc/PID/exe | |
-g GID group ID of the process owner | |
Default: obtained from /proc/PID/exe | |
-t TIME time of the dump (expressed as a unix timestamp) | |
Default: now (get from the date command) | |
-e NAME name of the executable being dumped | |
Default: obtained from PATH | |
-L hard-link the executable to DEST too (or copy it, if it can't | |
be hard-linked, for example because it's on a different | |
device), using the .exe suffix (useful to keep the original | |
executable untouched, even if it gets updated in the original | |
location) | |
-l soft-link the executable to DEST too, using the .symlink suffix | |
(useful to get what was the original executable location) | |
EOT | |
} | |
die() | |
{ | |
status=$1 | |
shift && true | |
exec >&2 | |
echo "Error: $@" | |
usage | |
exit $status | |
} | |
is_uint() | |
{ | |
echo "$1" | egrep -q -- '^[0-9]+$' | |
} | |
OPTIND=1 | |
while getopts "hLlk:d:u:g:t:e:" o; do | |
case "$o" in | |
k) | |
keep=${OPTARG} | |
is_uint "$keep" || | |
die 2 "MAX should be an unsigned int" | |
;; | |
d) | |
dest=${OPTARG} | |
;; | |
u) | |
uid=${OPTARG} | |
;; | |
g) | |
gid=${OPTARG} | |
;; | |
t) | |
time=${OPTARG} | |
;; | |
e) | |
exe_name=${OPTARG} | |
;; | |
L) | |
hard_link=1 | |
;; | |
l) | |
soft_link=1 | |
;; | |
h) | |
usage | |
exit 0; | |
;; | |
*) | |
exec >&2 | |
echo | |
usage | |
exit 2 | |
;; | |
esac | |
done | |
shift $(($OPTIND-1)) | |
pid="$1" | |
test -z "$pid" && | |
die 2 "PID missing" | |
test ! -d /proc/$pid && | |
die 2 "PID not present in /proc" | |
exe_path=$(readlink -f /proc/$pid/exe) | |
test -z "$exe_name" && | |
exe_name=$(basename "$exe_path") | |
test -z "$uid" && | |
uid=$(stat --printf=%u "`readlink -f /proc/$pid/exe`") | |
test -z "$gid" && | |
gid=$(stat --printf=%g "`readlink -f /proc/$pid/exe`") | |
test -z "$time" && | |
time=$(date +%s) | |
touch=$(date -d @$time +%Y%m%d%H%M.%S) | |
time=$(date -d @$time +%Y%m%d%H%M%S) | |
expr "$dest" : '^cwd/\|cwd$' > /dev/null && | |
dest=$(readlink -f /proc/$pid/cwd)$(echo "$dest" | cut -b4-) | |
expr "$dest" : '^exe/\|exe$' > /dev/null && | |
dest=$(dirname "$exe_path")$(echo "$dest" | cut -b4-) | |
test "$(echo $dest | cut -b1)" != / && | |
die 2 "$dest is not an absolute path" | |
umask 0077 | |
basename=$dest/$exe_name-${time}_$pid | |
mkdir -p "$dest" | |
test $hard_link -eq 1 && { | |
ln -f "$exe_path" "$basename.exe" 2>/dev/null || | |
cp -f "$exe_path" "$basename.exe" | |
chown $uid:$gid "$basename.exe" | |
touch -c -h -t $touch "$basename.exe" | |
} | |
test $soft_link -eq 1 && { | |
ln -sf "$exe_path" "$basename.symlink" | |
chown -h $uid:$gid "$basename.symlink" | |
touch -c -h -t $touch "$basename.symlink" | |
} | |
cat > "$basename.core" | |
chown $uid:$gid "$basename.core" | |
touch -c -h -t $touch "$basename.core" | |
test $keep -eq 0 && | |
exit 0 | |
ls -t "$dest/$exe_name-"*.core | | |
sed -e "1,${keep}d" -e 's/^\(.*\).core$/\1.core\n\1.exe\n\1.symlink/' | | |
xargs -rd'\n' rm -f |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment