ba0aa24316
Add ssh dump support changes including below items: 1. sshkey option 2. sshkey propagate 3. fix a bug of _server ip calculation for dump target string 4. change the prefix of kdump hook from 93 to 01 to avoid dhclient and other cleanups happening before us 5. enable network with dracut cmdline rd.neednet=1 when there's network target config [v1 - v2]: Only check_ssh_target when there's ssh dump target in kdump config file [v2 -> v3] style fixes: trailing spaces and space before tab indent remove set -x simply check_ssh_target use awk to get sshkey option value change pivot hook order to 0000 Signed-off-by: Dave Young <dyoung@redhat.com>
380 lines
8.4 KiB
Bash
Executable File
380 lines
8.4 KiB
Bash
Executable File
#! /bin/sh
|
|
KEXEC=/sbin/kexec
|
|
|
|
# Will be different for ia64, for example. For now, that architecture isn't
|
|
# supported. Code needs to be added here when we do.
|
|
BOOTDIR="/boot"
|
|
|
|
KDUMP_KERNELVER=""
|
|
KDUMP_COMMANDLINE=""
|
|
KEXEC_ARGS=""
|
|
KDUMP_CONFIG_FILE="/etc/kdump.conf"
|
|
MKDUMPRD="/sbin/mkdumprd -d -f"
|
|
SAVE_PATH=/var/crash
|
|
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
|
|
DUMP_TARGET=""
|
|
|
|
LOGGER="/usr/bin/logger -p info -t kdump"
|
|
|
|
standard_kexec_args="-p"
|
|
|
|
if [ -f /etc/sysconfig/kdump ]; then
|
|
. /etc/sysconfig/kdump
|
|
fi
|
|
|
|
function save_core()
|
|
{
|
|
coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`"
|
|
|
|
mkdir -p $coredir
|
|
cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete
|
|
if [ $? == 0 ]; then
|
|
mv $coredir/vmcore-incomplete $coredir/vmcore
|
|
$LOGGER "saved a vmcore to $coredir"
|
|
else
|
|
$LOGGER "failed to save a vmcore to $coredir"
|
|
fi
|
|
|
|
# pass the dmesg to Abrt tool if exists, in order
|
|
# to collect the kernel oops message.
|
|
# https://fedorahosted.org/abrt/
|
|
if [ -x /usr/bin/dumpoops ]; then
|
|
makedumpfile --dump-dmesg $coredir/vmcore $coredir/dmesg >/dev/null 2>&1
|
|
dumpoops -d $coredir/dmesg >/dev/null 2>&1
|
|
if [ $? == 0 ]; then
|
|
$LOGGER "kernel oops has been collected by abrt tool"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function check_config()
|
|
{
|
|
if [ -z "$KDUMP_KERNELVER" ]; then
|
|
kdump_kver=`uname -r`
|
|
else
|
|
kdump_kver=$KDUMP_KERNELVER
|
|
fi
|
|
|
|
kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
|
|
kdump_initrd="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img"
|
|
|
|
if [ ! -f $kdump_kernel ]; then
|
|
echo -n "No kdump kernel image found."; echo
|
|
echo "Tried to locate ${kdump_kernel}"
|
|
return 0
|
|
fi
|
|
|
|
if [ ! -f $kdump_initrd ]; then
|
|
echo -n "No kdump initial ramdisk found."; echo
|
|
echo "Rebuilding $kdump_initrd"
|
|
$MKDUMPRD $kdump_initrd $kdump_kver
|
|
if [ $? != 0 ]; then
|
|
echo "Failed to run mkdumprd"
|
|
$LOGGER "mkdumprd: failed to make kdump initrd"
|
|
exit 1
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
#check to see if config file has been modified after
|
|
#last build of the image file
|
|
config_time=0
|
|
if [ -f $KDUMP_CONFIG_FILE ]; then
|
|
config_time=`stat -c "%Y" $KDUMP_CONFIG_FILE`
|
|
fi
|
|
kernel_time=`stat -c "%Y" $kdump_kernel`
|
|
image_time=`stat -c "%Y" $kdump_initrd`
|
|
|
|
if [ "$config_time" -gt "$image_time" ] ||
|
|
[ "$kernel_time" -gt "$image_time" ]; then
|
|
echo "Detected $KDUMP_CONFIG_FILE or $kdump_kernel change"
|
|
echo "Rebuilding $kdump_initrd"
|
|
$MKDUMPRD $kdump_initrd $kdump_kver
|
|
if [ $? != 0 ]; then
|
|
echo "Failed to run mkdumprd"
|
|
$LOGGER "mkdumprd: failed to make kdump initrd"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
}
|
|
|
|
# This function check iomem and determines if we have more than
|
|
# 4GB of ram available. Returns 1 if we do, 0 if we dont
|
|
function need_64bit_headers()
|
|
{
|
|
return `tail -n 1 /proc/iomem | awk '{ split ($1, r, "-"); \
|
|
print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'`
|
|
}
|
|
|
|
# Load the kdump kerel specified in /etc/sysconfig/kdump
|
|
# If none is specified, try to load a kdump kernel with the same version
|
|
# as the currently running kernel.
|
|
function load_kdump()
|
|
{
|
|
|
|
if [ -z "$KDUMP_COMMANDLINE" ]
|
|
then
|
|
KDUMP_COMMANDLINE=`cat /proc/cmdline`
|
|
fi
|
|
|
|
ARCH=`uname -m`
|
|
if [ "$ARCH" == "ppc64" ]
|
|
then
|
|
MEM_RESERVED=`grep "crashkernel=[0-9]\+[MmKkGg]@[0-9]\+[MmGgKk]" /proc/cmdline`
|
|
if [ -z "$MEM_RESERVED" ]
|
|
then
|
|
MEM_RESERVED=`grep "crashkernel=[0-9]\+[MmKkGg]" /proc/cmdline`
|
|
fi
|
|
else
|
|
MEM_RESERVED=`grep "Crash kernel" /proc/iomem | grep -v "00000000-00000000"`
|
|
fi
|
|
|
|
if [ -z "$MEM_RESERVED" ]
|
|
then
|
|
$LOGGER "No crashkernel parameter specified for running kernel"
|
|
return 1
|
|
fi
|
|
|
|
if [ "$ARCH" == "i686" -o "$ARCH" == "i386" ]
|
|
then
|
|
|
|
need_64bit_headers
|
|
if [ $? == 1 ]
|
|
then
|
|
FOUND_ELF_ARGS=`echo $KEXEC_ARGS | grep elf32-core-headers`
|
|
if [ -n "$FOUND_ELF_ARGS" ]
|
|
then
|
|
echo -n "Warning: elf32-core-headers overrides correct elf64 setting"
|
|
echo
|
|
else
|
|
KEXEC_ARGS="$KEXEC_ARGS --elf64-core-headers"
|
|
fi
|
|
else
|
|
FOUND_ELF_ARGS=`echo $KEXEC_ARGS | grep elf64-core-headers`
|
|
if [ -z "$FOUND_ELF_ARGS" ]
|
|
then
|
|
KEXEC_ARGS="$KEXEC_ARGS --elf32-core-headers"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
KDUMP_COMMANDLINE=`echo $KDUMP_COMMANDLINE | sed -e 's/crashkernel=[^ ]*//'`
|
|
KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} ${KDUMP_COMMANDLINE_APPEND}"
|
|
|
|
$KEXEC $KEXEC_ARGS $standard_kexec_args \
|
|
--command-line="$KDUMP_COMMANDLINE" \
|
|
--initrd=$kdump_initrd $kdump_kernel 2>/dev/null
|
|
if [ $? == 0 ]; then
|
|
$LOGGER "kexec: loaded kdump kernel"
|
|
return 0
|
|
else
|
|
$LOGGER "kexec: failed to load kdump kernel"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function check_ssh_config()
|
|
{
|
|
while read config_opt config_val; do
|
|
case "$config_opt" in
|
|
sshkey)
|
|
if [ -f "$config_val" ]; then
|
|
# canonicalize the path
|
|
SSH_KEY_LOCATION=$(/usr/bin/readlink -m $config_val)
|
|
else
|
|
echo "WARNING: '$config_val' doesn't exist, using default value '$SSH_KEY_LOCATION'"
|
|
fi
|
|
;;
|
|
path)
|
|
SAVE_PATH=$config_val
|
|
;;
|
|
net)
|
|
DUMP_TARGET=$config_val
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
done < $KDUMP_CONFIG_FILE
|
|
|
|
#make sure they've configured kdump.conf for ssh dumps
|
|
local SSH_TARGET=`echo -n $DUMP_TARGET|sed '/.*@/p'`
|
|
if [ -z "$SSH_TARGET" ]; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function check_ssh_target()
|
|
{
|
|
ssh -q -i $SSH_KEY_LOCATION -o BatchMode=yes $DUMP_TARGET mkdir -p $SAVE_PATH
|
|
if [ $? -ne 0 ]; then
|
|
echo "Could not create $DUMP_TARGET:$SAVE_PATH, you probably need to run \"service kdump propagate\""
|
|
exit $?
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function propagate_ssh_key()
|
|
{
|
|
check_ssh_config
|
|
if [ $? -ne 0 ]; then
|
|
echo "No ssh config specified in $KDUMP_CONFIG_FILE. Can't propagate"
|
|
$LOGGER "$errmsg, no ssh config specified in $KDUMP_CONFIG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
#Check if selinux is on... must flip to permissive mode
|
|
#for the moment to create key, then flip back...
|
|
se_enforce=`/usr/sbin/sestatus | grep -c "^Current mode.*enforcing"`
|
|
if [ "$se_enforce" -ge 1 ]; then
|
|
/usr/sbin/setenforce 0 2>&1 > /dev/null
|
|
fi
|
|
|
|
local KEYFILE=$SSH_KEY_LOCATION
|
|
local errmsg="Failed to propagate ssh key"
|
|
|
|
#Check to see if we already created key, if not, create it.
|
|
if [ -f $KEYFILE ]; then
|
|
echo "Using existing keys..."
|
|
else
|
|
echo -n "Generating new ssh keys... "
|
|
/usr/bin/ssh-keygen -t rsa -f $KEYFILE -N "" 2>&1 > /dev/null
|
|
echo "done."
|
|
fi
|
|
|
|
#If necessary, flip selinux back to enforcing
|
|
if [ "$se_enforce" -ge 1 ]; then
|
|
/usr/sbin/setenforce 1 2>&1 > /dev/null
|
|
fi
|
|
|
|
#now find the target ssh user and server to contact.
|
|
SSH_USER=`echo $DUMP_TARGET | cut -d\ -f2 | cut -d@ -f1`
|
|
SSH_SERVER=`echo $DUMP_TARGET | sed -e's/\(.*@\)\(.*$\)/\2/'`
|
|
|
|
#now send the found key to the found server
|
|
ssh-copy-id -i $KEYFILE $SSH_USER@$SSH_SERVER
|
|
RET=$?
|
|
if [ $RET == 0 ]; then
|
|
echo $KEYFILE has been added to ~$SSH_USER/.ssh/authorized_keys on $SSH_SERVER
|
|
$LOGGER "propagated ssh key (ssh server: $SSH_SERVER)"
|
|
return 0
|
|
else
|
|
echo $KEYFILE failed in transfer to $SSH_SERVER
|
|
$LOGGER "$errmsg, unable to transfer $KEYFILE to $SSH_SERVER"
|
|
exit 1
|
|
fi
|
|
|
|
}
|
|
|
|
function status()
|
|
{
|
|
if [ ! -e /sys/kernel/kexec_crash_loaded ]
|
|
then
|
|
return 2
|
|
fi
|
|
rc=`cat /sys/kernel/kexec_crash_loaded`
|
|
if [ $rc == 1 ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function start()
|
|
{
|
|
#TODO check raw partition for core dump image
|
|
status
|
|
rc=$?
|
|
if [ $rc == 2 ]; then
|
|
echo -n "Kdump is not supported on this kernel"; echo
|
|
return 1;
|
|
else
|
|
if [ $rc == 0 ]; then
|
|
echo -n "Kdump already running"; echo
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
check_ssh_config && check_ssh_target
|
|
|
|
check_config
|
|
if [ $? != 0 ]; then
|
|
echo -n "Starting kdump:"; echo
|
|
$LOGGER "failed to start up, config file incorrect"
|
|
return 1
|
|
fi
|
|
load_kdump
|
|
if [ $? != 0 ]; then
|
|
echo -n "Starting kdump:"; echo
|
|
$LOGGER "failed to start up"
|
|
return 1
|
|
fi
|
|
|
|
echo -n "Starting kdump:"; echo
|
|
$LOGGER "started up"
|
|
}
|
|
|
|
function stop()
|
|
{
|
|
$KEXEC -p -u 2>/dev/null
|
|
if [ $? == 0 ]; then
|
|
$LOGGER "kexec: unloaded kdump kernel"
|
|
echo -n "Stopping kdump:"; echo
|
|
$LOGGER "stopped"
|
|
return 0
|
|
else
|
|
$LOGGER "kexec: failed to unload kdump kernel"
|
|
echo -n "Stopping kdump:"; echo
|
|
$LOGGER "failed to stop"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
case "$1" in
|
|
start)
|
|
if [ -s /proc/vmcore ]; then
|
|
save_core
|
|
reboot
|
|
else
|
|
start
|
|
fi
|
|
;;
|
|
stop)
|
|
stop
|
|
;;
|
|
status)
|
|
EXIT_CODE=0
|
|
status
|
|
case "$?" in
|
|
0)
|
|
echo "Kdump is operational"
|
|
EXIT_CODE=0
|
|
;;
|
|
1)
|
|
echo "Kdump is not operational"
|
|
EXIT_CODE=3
|
|
;;
|
|
2)
|
|
echo "Kdump is unsupported on this kernel"
|
|
EXIT_CODE=3
|
|
;;
|
|
esac
|
|
exit $EXIT_CODE
|
|
;;
|
|
restart)
|
|
stop
|
|
start
|
|
;;
|
|
condrestart)
|
|
;;
|
|
propagate)
|
|
propagate_ssh_key
|
|
;;
|
|
*)
|
|
echo $"Usage: $0 {start|stop|status|restart|propagate}"
|
|
exit 1
|
|
esac
|
|
|
|
exit $?
|