Package: makedumpfile
Version: 1:1.6.1-1
Severity: wishlist
Tags: patch

Hi,

Some users might want to store core dumps in the same place as kernel
dumps (especially when storing them on a remote machine). To avoid
having to configure two scripts, add a dump-core script to kdump-tools.
It will use the same configuration file as kdump-tools.

Set /proc/sys/kernel/core_pattern to pipe the core dumps to dump-core.
You can use following sysctl configuration file:

  $ cat /etc/sysctl.d/50-dump-core.conf
  kernel.core_pattern = |/usr/share/kdump-tools/dump-core %e-pid%p-sig%s-%t
  # 2 = "suidsafe": Any binary which normally would not be dumped (see "0")
  # is dumped readable by root only.
  fs.suid_dumpable = 2
  $ sysctl -p /etc/sysctl.d/50-dump-core.conf

A patch is attached. Please review it carefully. Some could is
duplicated and probably should be placed in a shell library file.

-- 
Benjamin Drung
System Developer
Debian & Ubuntu Developer

ProfitBricks GmbH
Greifswalder Str. 207
D - 10405 Berlin

Email: [email protected]
URL:  http://www.profitbricks.com

Sitz der Gesellschaft: Berlin.
Registergericht: Amtsgericht Charlottenburg, HRB 125506B.
Geschäftsführer: Andreas Gauger, Achim Weiss.
>From 593ccd06abec57d55dcb116226df6375f03b2ca2 Mon Sep 17 00:00:00 2001
From: Benjamin Drung <[email protected]>
Date: Thu, 9 Mar 2017 19:33:00 +0100
Subject: [PATCH] Add dump-core script

Some users might want to store core dumps in the same place as kernel
dumps (especially when storing them on a remote machine). To avoid
having to configure two scripts, add a dump-core script to kdump-tools.
It will use the same configuration file as kdump-tools.

Set /proc/sys/kernel/core_pattern to pipe the core dumps to dump-core.
You can use following sysctl configuration file:

  $ cat /etc/sysctl.d/50-dump-core.conf
  kernel.core_pattern = |/usr/share/kdump-tools/dump-core %e-pid%p-sig%s-%t
  # 2 = "suidsafe": Any binary which normally would not be dumped (see "0")
  # is dumped readable by root only.
  fs.suid_dumpable = 2
  $ sysctl -p /etc/sysctl.d/50-dump-core.conf
---
 debian/dump-core           | 283 +++++++++++++++++++++++++++++++++++++++++++++
 debian/kdump-tools.install |   1 +
 2 files changed, 284 insertions(+)
 create mode 100755 debian/dump-core

diff --git a/debian/dump-core b/debian/dump-core
new file mode 100755
index 0000000..2e0d15a
--- /dev/null
+++ b/debian/dump-core
@@ -0,0 +1,283 @@
+#!/bin/bash
+set -u
+
+# Copyright (C) 2017, ProfitBricks GmbH
+# Authors: Benjamin Drung <[email protected]>
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# This tool can be used to store core dumps the same way as kernel dumps.
+# Set /proc/sys/kernel/core_pattern to pipe the core dumps to this tool.
+# You can use following sysctl configuration file:
+#
+#   $ cat /etc/sysctl.d/50-dump-core.conf
+#   kernel.core_pattern = |/usr/share/kdump-tools/dump-core %e-pid%p-sig%s-%t
+#   # 2 = "suidsafe": Any binary which normally would not be dumped (see "0")
+#   # is dumped readable by root only.
+#   fs.suid_dumpable = 2
+#   $ sysctl -p /etc/sysctl.d/50-dump-core.conf
+
+exec > >(logger -t "${0}" -p syslog.info) 2> >(logger -t "${0}" -p syslog.warn)
+
+echo "Called with parameters: $@"
+
+# Global Setup
+KDUMP_DEFAULTS=/etc/default/kdump-tools
+[ -r $KDUMP_DEFAULTS ] && . $KDUMP_DEFAULTS
+
+# Set up defaults
+KDUMP_COREDIR=${KDUMP_COREDIR:=/var/crash}
+NFS_TIMEO=${NFS_TIMEO:=600}
+NFS_RETRANS=${NFS_RETRANS:=3}
+KDUMP_STAMP=${1-$(date -u +%Y%m%d-%H%M%S.%N)}
+
+
+#
+# Return the name of the subdirectory to store core file.
+#	Will add hostname/IP according to the value of
+#	HOSTTAG if networked dump is selected
+
+define_stampdir()
+{
+	STAMP=$1
+	HOSTTAG="${HOSTTAG:=ip}"
+
+	if [ -z "${SSH-}" ] && [ -z "${NFS-}" ] && [ -z "${FTP-}" ]; then
+		echo "$KDUMP_COREDIR/$STAMP"
+	elif [ "$HOSTTAG" = "hostname" ];then
+		echo "$KDUMP_COREDIR/$(hostname)-$STAMP"
+	else
+		# Looping to give time to network to settle
+		local counter=0
+		while [ $counter -lt 5 ];do
+			THIS_HOST="$(ip addr show up | grep -w inet | tail -n1 | awk '{print $2}' | cut -f1  -d'/')"
+			set -- $THIS_HOST
+			THIS_HOST=$1
+			if [ -z "$THIS_HOST" ]; then
+				sleep 1
+				counter=$(($counter + 1))
+			else
+				break
+			fi
+		done
+		if [ -z "$THIS_HOST" ]; then
+			# Send log msg to stderr to avoid polluting
+			# the result of the function
+			echo "Unable to get IP from network" >&2
+			echo "Reverting to HOSTTAG=hostname" >&2
+			THIS_HOST="$(hostname)"
+		fi
+		echo "$KDUMP_COREDIR/$THIS_HOST-$STAMP"
+	fi
+}
+
+compress() {
+	if [ "$KDUMP_COMPRESSION" = "bzip2" ]; then
+		bzip2 -c
+	elif [ "$KDUMP_COMPRESSION" = "gzip" ]; then
+		gzip -c
+	elif [ "$KDUMP_COMPRESSION" = "lz4" ]; then
+		lz4 -c
+	elif [ "$KDUMP_COMPRESSION" = "xz" ]; then
+		/usr/bin/xz -c
+	else
+		cat
+	fi
+}
+
+compression_extension() {
+	if [ "$KDUMP_COMPRESSION" = "bzip2" ]; then
+		echo ".bz2"
+	elif [ "$KDUMP_COMPRESSION" = "gzip" ]; then
+		echo ".gz"
+	elif [ "$KDUMP_COMPRESSION" = "lz4" ]; then
+		echo ".lz4"
+	elif [ "$KDUMP_COMPRESSION" = "xz" ]; then
+		echo ".xz"
+	fi
+}
+
+dump_local()
+{
+	KDUMP_STAMPDIR=$(define_stampdir $KDUMP_STAMP)
+	KDUMP_CORETEMP="$KDUMP_STAMPDIR/coredump-incomplete$(compression_extension)"
+	KDUMP_COREFILE="$KDUMP_STAMPDIR/coredump.$KDUMP_STAMP$(compression_extension)"
+
+	# If we use NFS, verify that we can mount the FS
+	#
+	if [ -n "${NFS-}" ];then
+		echo "Mounting NFS mountpoint $NFS ..."
+		mount -t nfs -o nolock -o tcp -o soft -o timeo=${NFS_TIMEO} -o retrans=${NFS_RETRANS} $NFS $KDUMP_COREDIR
+		ERROR=$?
+		if [ $ERROR -ne 0 ];then
+			echo "Unable to mount remote NFS directory $NFS. Cannot save core dump" >&2
+			return 1;
+		fi
+
+		# FS is mounted, see if we can write to it
+		#
+		mkdir -p $KDUMP_STAMPDIR
+		ERROR=$?
+
+		if [ $ERROR -ne 0 ];then
+			echo "Unable to write to the remote NFS directory $NFS. Cannot save core dump" >&2
+			umount $KDUMP_COREDIR
+			UMNT_ERROR=$?
+			if [ $UMNT_ERROR -ne 0 ];then
+				echo "Unable to cleanly unmount the NFS file system" >&2
+			fi
+		else
+			echo "Dumping to NFS mountpoint $NFS/$KDUMP_STAMP"
+		fi
+	else
+		mkdir -p $KDUMP_STAMPDIR
+	fi
+
+	compress > $KDUMP_CORETEMP
+	ERROR=$?
+
+	# did we succeed?
+	if [ $ERROR -eq 0 ]; then
+		mv $KDUMP_CORETEMP $KDUMP_COREFILE
+		echo "saved core dump in $KDUMP_STAMPDIR"
+		sync
+	else
+		echo "failed to save core dump in $KDUMP_STAMPDIR" >&2
+	fi
+
+	# If we use NFS, umount the remote FS
+	#
+	if [ -n "$NFS" ];then
+		umount $KDUMP_COREDIR
+		UMNT_ERROR=$?
+		if [ $UMNT_ERROR -ne 0 ] ; then
+			echo "Unable to cleanly unmount the NFS file system" >&2
+		fi
+	fi
+
+	return $ERROR
+}
+
+dump_to_ftp()
+{
+	KDUMP_REMOTE_HOST="${FTP%%:*}"
+	local fqdn=$(host "${KDUMP_REMOTE_HOST}" | grep -v "not found" | tail -n 1 | cut -d " " -f 1 || echo "${KDUMP_REMOTE_HOST}")
+	KDUMP_COREDIR="${FTP#*:}"
+	if [ "$KDUMP_COREDIR" = "$FTP" ]; then
+		# No colon in FTP specified. Assuming / as path
+		KDUMP_COREDIR="/"
+	fi
+
+	KDUMP_STAMPDIR=$(define_stampdir "")
+
+	KDUMP_COREFILE="${KDUMP_STAMPDIR}$KDUMP_STAMP$(compression_extension)"
+	KDUMP_PACKAGES_FILE="${KDUMP_STAMPDIR}${KDUMP_STAMP}-packages.txt"
+	ERROR=0
+
+	FTPPUT_ARGS=""
+	if [ -n "${FTP_USER-}" ]; then
+		FTPPUT_ARGS="$FTPPUT_ARGS -u $FTP_USER"
+	fi
+	if [ -n "${FTP_PASSWORD-}" ]; then
+		FTPPUT_ARGS="$FTPPUT_ARGS -p $FTP_PASSWORD"
+	fi
+	if [ -n "${FTP_PORT-}" ]; then
+		FTPPUT_ARGS="$FTPPUT_ARGS -P $FTP_PORT"
+	fi
+
+	compress | busybox ftpput $FTPPUT_ARGS $KDUMP_REMOTE_HOST $KDUMP_COREFILE -
+	ERROR=$?
+
+	# did we succeed?
+	if [ $ERROR -ne 0 ]; then
+		echo "failed to save vmcore via FTP in $fqdn:$KDUMP_COREFILE" >&2
+	else
+		echo "saved core dump via FTP in $fqdn:$KDUMP_COREFILE"
+	fi
+
+	# dump the package list
+	dpkg-query -f='${Package}=${Version}\n' -W | busybox ftpput $FTPPUT_ARGS $KDUMP_REMOTE_HOST $KDUMP_PACKAGES_FILE -
+	ERROR=$?
+	# did we succeed?
+	if [ $ERROR == 0 ]; then
+		echo "saved installed packages list via FTP in $fqdn:$KDUMP_PACKAGES_FILE"
+	else
+		echo "failed to save saved installed packages via FTP in $fqdn:$KDUMP_PACKAGES_FILE" >&2
+	fi
+
+	return $ERROR
+}
+
+dump_to_ssh()
+{
+	KDUMP_SSH_KEY="${SSH_KEY:=/root/.ssh/kdump_id_rsa}"
+	KDUMP_REMOTE_HOST="$SSH"
+
+	KDUMP_STAMPDIR=$(define_stampdir $KDUMP_STAMP)
+
+	KDUMP_CORETEMP="$KDUMP_STAMPDIR/coredump-incomplete$(compression_extension)"
+	KDUMP_COREFILE="$KDUMP_STAMPDIR/coredump.$KDUMP_STAMP$(compression_extension)"
+	KDUMP_PACKAGES_FILE="${KDUMP_STAMPDIR}/installed-packages.txt"
+	ERROR=0
+
+	ssh -i $KDUMP_SSH_KEY $KDUMP_REMOTE_HOST mkdir -p $KDUMP_STAMPDIR
+	ERROR=$?
+	# If remote connections fails, no need to continue
+	if [ $ERROR -ne 0 ] ; then
+		echo "Unable to reach remote server $KDUMP_REMOTE_HOST. No reason to continue" >&2
+		return 1
+	fi
+
+	echo "sending makedumpfile $MAKEDUMP_ARGS $vmcore_file to $KDUMP_REMOTE_HOST : $KDUMP_CORETEMP"
+	compress | ssh -i $KDUMP_SSH_KEY $KDUMP_REMOTE_HOST dd of=$KDUMP_CORETEMP
+	ERROR=$?
+	if [ $ERROR -ne 0 ] ; then
+		echo "makedumpfile scp failed. The core dump file will not be available" >&2
+	else
+		ERROR=0
+	fi
+
+	# did we succeed?
+	if [ $ERROR -ne 0 ]; then
+		echo "failed to save core dump in $KDUMP_REMOTE_HOST:$KDUMP_STAMPDIR" >&2
+		sync
+	else
+		ssh -i $KDUMP_SSH_KEY $KDUMP_REMOTE_HOST mv $KDUMP_CORETEMP $KDUMP_COREFILE
+		echo "saved vmcore in $KDUMP_REMOTE_HOST:$KDUMP_STAMPDIR"
+	fi
+
+	# dump the package list
+	dpkg-query -f='${Package}=${Version}\n' -W | ssh -i $KDUMP_SSH_KEY $KDUMP_REMOTE_HOST dd of=$KDUMP_PACKAGES_FILE
+	ERROR=$?
+	# did we succeed?
+	if [ $ERROR == 0 ]; then
+		echo "saved installed packages list via SSH in $KDUMP_REMOTE_HOST:$KDUMP_PACKAGES_FILE"
+	else
+		echo "failed to save saved installed packages via SSH in $KDUMP_REMOTE_HOST:$KDUMP_PACKAGES_FILE" >&2
+	fi
+
+	return $ERROR
+}
+
+if test -n "${KDUMP_TASKSET_CORES-}"; then
+	taskset -p -c "${KDUMP_TASKSET_CORES}" $$ || true
+fi
+
+if [ -n "${FTP-}" ]; then
+	dump_to_ftp
+elif [ -n "${SSH-}" ]; then
+	dump_to_ssh
+else
+	dump_local
+fi
+exit $?
diff --git a/debian/kdump-tools.install b/debian/kdump-tools.install
index 86ef7e4..fb54352 100644
--- a/debian/kdump-tools.install
+++ b/debian/kdump-tools.install
@@ -1 +1,2 @@
 debian/kdump-config	/usr/sbin
+debian/dump-core	/usr/share/kdump-tools
-- 
2.9.3

Reply via email to