Skip to content

Instantly share code, notes, and snippets.

@leandro-lucarella-sociomantic
Last active August 29, 2015 14:11
Show Gist options
  • Save leandro-lucarella-sociomantic/f36a77d49dd3515f207c to your computer and use it in GitHub Desktop.
Save leandro-lucarella-sociomantic/f36a77d49dd3515f207c to your computer and use it in GitHub Desktop.
A better core dump file writer
#!/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