# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*- # vim: set filetype=sh sw=3 sts=3 expandtab autoindent: # # this handler will save various reports of vital system information. # by default, all the reports are saved in /var/backups. # # (1) a capture of the debconf package selection states. This file # can be used to restore the answers to debconf questions for # packages that you will be installing through (2) below. To # do this, run: "debconf-set-selections < debconfsel.txt" # # (2) a list of all the packages installed and removed. # this file can be used to restore the state of installed packages # by running "dpkg --set-selections < dpkg-selections.txt and # then run "apt-get -u dselect-upgrade". If you have the # debconf-set-selections file from (1), you should restore those first. # # (3) the partition table of all disks. # this partition table can be used to format another disk of # the same size. this can be handy if using software raid and # you have a disk go bad. just replace the disk and partition it # by running "sfdisk /dev/sdb < partitions.sdb.txt" # (MAKE SURE YOU PARTITION THE CORRECT DISK!!!) # # (4) hardware information. # write to a text file the important things which hwinfo can gleen. # # (5) the LUKS header of every LUKS block device, if option luksheaders # is enabled. # in case you (have to) scramble such a LUKS header (for some time), # and restore it later by running "dd if=luksheader.sda2.bin of=/dev/sda2" # (MAKE SURE YOU PASS THE CORRECT DEVICE AS of= !!!) # # (6) LVM metadata for every detected volume group, if "lvm = yes" # # (7) a copy of each device's MBR, if "mbr = yes". A master boot record # (MBR) is the 512-byte boot sector that is the first sector of a # partitioned data storage device of a hard disk. To restore the MBR # one could do something like: dd if=sda.mbr of=/dev/sda # (MAKE SURE YOU PASS THE CORRECT DEVICE AS of= !!!) # WARNING: Restoring the MBR with a mismatching partition table will # make your data unreadable and nearly impossible to recover # # (8) a copy of the BIOS, if "bios = yes" and flashrom is installed if [ -f /etc/debian_version ] then os=debian debug "Debian detected" osversion="/etc/debian_version" elif [ -f /etc/redhat-release ] then os=redhat debug "Redhat detected" osversion="/etc/redhat-release" elif [ -f /etc/SuSE-release ] then os=suse debug "SuSE detected" osversion="/etc/SuSE-release" else warning "Unknown OS detected!" fi getconf parentdir /var/backups getconf packages yes getconf dosfdisk yes getconf dohwinfo yes if [ ! -d $parentdir ]; then mkdir -p $parentdir fi if [ "$os" = "debian" ] then getconf packagesfile $parentdir/dpkg-selections.txt getconf packagemgr `which dpkg` getconf packagemgroptions ' --get-selections *' getconf selectionsfile $parentdir/debconfsel.txt getconf debconfgetselections `which debconf-get-selections` elif [ "$os" = "redhat" ] then getconf packagesfile $parentdir/rpmpackages.txt getconf packagemgr `which rpm` getconf packagemgroptions ' -qa ' getconf SYSREPORT `which sysreport` getconf sysreport_options ' -norpm ' elif [ "$os" = "suse" ] then getconf packagesfile $parentdir/rpmpackages.txt getconf packagemgr `which rpm` getconf packagemgroptions ' -qa ' else getconf packagesfile $parentdir/unknownOS.txt fi packagemgroptions="${packagemgroptions//__star__/*}" getconf partitions yes getconf partitionsfile $parentdir/partitions.__star__.txt getconf hardware yes getconf hardwarefile $parentdir/hardware.txt getconf sysreport yes getconf sysreportfile $parentdir/sysreport.txt getconf SFDISK `which sfdisk` getconf HWINFO `which hwinfo` getconf LSBLK `which lsblk` getconf sfdisk_options "" getconf hwinfo_options "" getconf CRYPTSETUP `which cryptsetup` getconf DD `which dd` getconf luksheaders no getconf luksheadersfile $parentdir/luksheader.__star__.bin getconf VGS `which vgs` getconf VGCFGBACKUP `which vgcfgbackup` getconf lvm no getconf mbr no getconf mbrfile $parentdir/mbr.__star__.bin getconf FLASHROM `which flashrom` getconf bios no getconf vsnames all # If vservers are configured, check that the ones listed in $vsnames are running. usevserver=no if [ $vservers_are_available = yes ]; then if [ "$vsnames" = all ]; then vsnames="$found_vservers" fi if ! vservers_running "$vsnames" ; then fatal "At least one of the vservers listed in vsnames ($vsnames) is not running." fi info "Using vservers '$vsnames'" usevserver=yes fi ## SANITY CHECKS ######################### if [ "$luksheaders" == "yes" ]; then if [ ! -x "$DD" ]; then warning "can't find dd, skipping backup of LUKS headers." luksheaders="no" fi if [ ! -x "$CRYPTSETUP" ]; then warning "can't find cryptsetup, skipping backup of LUKS headers." luksheaders="no" fi fi if [ "$lvm" == "yes" ]; then if [ ! -x "$VGS" ]; then warning "can't find vgs, skipping backup of LVM metadata" lvm="no" fi if [ ! -x "$VGCFGBACKUP" ]; then warning "can't find vgcfgbackup, skipping backup of LVM metadata" lvm="no" fi fi if [ "$mbr" == "yes" ]; then if [ ! -x "$DD" ]; then warning "can't find dd, skipping backup of MBR." mbr="no" fi fi if [ "$bios" == "yes" ]; then if [ ! -x "$FLASHROM" ]; then warning "can't find flashrom, skipping backup of BIOS." mbr="no" fi fi ## PACKAGES ############################## # # here we grab a list of the packages installed and removed. # if [ "$packages" == "yes" ]; then if [ $usevserver = yes ]; then info "vserver root directory set to: $VROOTDIR" for vserver in $vsnames; do info "examining vserver: $vserver" # is it running ? vservers_running $vserver if [ $? -ne 0 ]; then warning "The vserver $vserver is not running." continue fi # is $packagemgr available inside $vserver ? if [ ! -x "${VROOTDIR}/${vserver}${packagemgr}" ]; then warning "can't find $packagemgr in vserver $vserver, skipping installed packages report." else # don't expand * since it can be used in $packagemgroptions set -o noglob debug "$VSERVER $vserver exec $packagemgr $packagemgroptions > $VROOTDIR/$vserver$packagesfile" $VSERVER $vserver exec $packagemgr $packagemgroptions > $VROOTDIR/$vserver$packagesfile || fatal "can not save $packagemgr info to $packagesfile" set +o noglob fi # is $debconfgetselections available inside $vserver ? found=no # case #1: it is available on the host, is it available inside $vserver ? if [ -n "$debconfgetselections" ]; then [ -x "${VROOTDIR}/${vserver}${debconfgetselections}" ] && found=yes # case #2: it is not available on the host, is it available inside $vserver ? else [ -n "`$VSERVER $vserver exec which debconf-get-selections`" ] && found=yes fi if [ "$found" != yes ]; then warning "can't find debconf-get-selections in vserver $vserver, skipping package selection states. You may want to install the debconf-utils package." else debug "$VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile" $VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile || fatal "can not save debconf-get-selections info to $selectionsfile" fi unset found done fi # We want to perform this on the host as well if [ -z "$packagemgr" -o ! -x "$packagemgr" ]; then warning "can't find ${packagemgr}, skipping installed packages report." else # don't expand * since it can be used in $packagemgroptions set -o noglob debug "$packagemgr $packagemgroptions > $packagesfile" $packagemgr $packagemgroptions > $packagesfile || fatal "can not save $packagemgr info to $packagesfile" set +o noglob fi if [ -z "$debconfgetselections" ]; then warning "can't find debconf-get-selections, skipping package selection states. You might want to install the debconf-utils package." else debug "$debconfgetselections > $selectionsfile" $debconfgetselections > $selectionsfile || fatal "can not save $debconfgetselections info to $selectionsfile" fi fi ## System report ############################## # # here we grab a bunch of system stuff for a report # export STATUS HASHES="#################################################################" DASHES="-----------------------------------------------------------------" cat /dev/null > $sysreportfile || fatal "can not write to $sysreportfile" catiffile () { echo $HASHES >> $sysreportfile echo "# $STATUS" >> $sysreportfile echo $HASHES >> $sysreportfile if [ -f $1 ]; then echo "file: $1" >> $sysreportfile echo $DASHES >> $sysreportfile cat $1 >> $sysreportfile 2>&1 || info "reading of $1 failed" fi if [ -d $1 ]; then echo "directory: $1" >> $sysreportfile echo $DASHES >> $sysreportfile for file in `find $1 -maxdepth 3 -noleaf -type f` do catiffile $file done fi echo $DASHES >> $sysreportfile } catifexec () { if [ -x $1 ]; then echo $HASHES >> $sysreportfile echo "# $STATUS" >> $sysreportfile echo $HASHES >> $sysreportfile $* >> $sysreportfile 2>&1 || info "executing of $1 failed" fi } STATUS="Determining $os version:" catiffile $osversion STATUS="Determinding your current hostname: " catifexec "/bin/hostname" STATUS="Getting the date:" catifexec "/bin/date" STATUS="Checking your systems current uptime and load average:" catifexec "/usr/bin/uptime" STATUS="Checking available memory:" catifexec "/usr/bin/free" STATUS="Checking free disk space:" catifexec "/bin/df" "-al --exclude-type=tmpfs" STATUS="Collecting what services run at what run level:" if [ $os = "redhat" ]; then catifexec "/sbin/chkconfig" "--list" STATUS="Collecting information about /etc/rc.d:" catiffile "/bin/ls /etc/rc.d/rc*.d/" elif [ $os = "debian" ]; then for level in 0 1 2 3 4 5 6 S; do echo "Level: $level" >> $sysreportfile for f in /etc/rc${level}.d/*; do # Remove /etc/Knn or Snn from beginning ff=$(echo $f | @SED@ 's_/etc/rc..d/[KS][0-9][0-9]__') if [ $f != $ff ]; then echo $ff >> $sysreportfile fi done echo "" >> $sysreportfile done fi STATUS="Getting bootloader information:" catifexec "/bin/ls" "-alR /boot" # This covers sparc, alpha, and intel (respectively) # updated for grub -mpg if [ -f /etc/silo.conf ]; then STATUS="Collecting information about the boot process (silo):" catiffile "/etc/silo.conf" fi if [ -f /etc/milo.conf ]; then STATUS="Collecting information about the boot process (milo):" catiffile "/etc/milo.conf" fi if [ -f /etc/lilo.conf ]; then STATUS="Collecting information about the boot process (lilo):" catiffile "/etc/lilo.conf" catifexec "/sbin/lilo" "-q" fi if [ -d /boot/grub -a -f /boot/grub/grub.conf -a -f /boot/grub/device.map ]; then STATUS="Collecting information about the boot process (grub.conf):" catiffile "/boot/grub/grub.conf" STATUS="Collecting information about the boot process (grub.map):" catiffile "/boot/grub/device.map" fi if [ -f /etc/cluster.conf -o -f /etc/cluster.xml ] ; then STATUS="Gathering information on cluster setup" # 2.1 AS if [ -f /etc/cluster.conf ] ; then catiffile "/etc/cluster.conf" fi # Taroon if [ -f /etc/cluster.xml ] ; then catiffile "/etc/cluster.xml" fi fi STATUS="Gathering sysctl information (sysctl -a):" catiffile "sysctl -a 2>/dev/null" STATUS="Gathering sysctl information (/etc/sysctl.conf):" catiffile "/etc/sysctl.conf" STATUS="Gathering IP information (/sbin/ifconfig):" catifexec "/sbin/ifconfig" "-a" STATUS="Gathering additional IP information (/bin/ip addr list):" catifexec "/bin/ip" "addr list" STATUS="Checking network routes:" catifexec "/sbin/route" "-n" STATUS="Collecting Name Service Switch config information:" catiffile "/etc/nsswitch.conf" STATUS="Collecting information about system authentication (pam):" catiffile "/etc/pam.conf" catiffile "/etc/pam.d" echo echo "Getting information about the kernel." echo STATUS="Getting kernel version:" catifexec "/bin/uname" "-a" if [ "$hardware" == "yes" ]; then STATUS="Checking module information:" catifexec "/sbin/lsmod" for x in $(/sbin/lsmod | /usr/bin/cut -f1 -d" " 2>/dev/null | /bin/grep -v Module 2>/dev/null ) ; do STATUS="Checking module information $x:" catifexec "/sbin/modinfo" "$x" done fi STATUS="Gathering information about your filesystems:" catiffile "/proc/filesystems" STATUS="Gathering information about your system stat:" catiffile "/proc/stat" STATUS="Gathering information about your partitions:" catiffile "/proc/partitions" STATUS="Gathering information about your ksyms:" catiffile "/proc/kallsyms" STATUS="Gathering information about slabinfo:" catiffile "/proc/slabinfo" # Added support to cover for the new modules.conf layout in Red Hat 7 STATUS="Collecting information regarding kernel modules" VER=`uname -r` catiffile "/lib/modules/$VER/modules.dep" if [ -f /etc/conf.modules ]; then STATUS="Collecting information regarding kernel modules (conf.modules)" catiffile "/etc/conf.modules" fi if [ -f /etc/modules.conf ]; then STATUS="Collecting information regarding kernel modules (modules.conf)" catiffile "/etc/modules.conf" fi if [ -f /etc/modprobe.conf ]; then STATUS="Collecting information regarding kernel modules (modeprobe.conf)" catiffile "/etc/modprobe.conf" fi # dkms status if [ -x /usr/sbin/dkms ] ; then STATUS="Gathering current status of modules, versions and kernels (dkms):" catifexec "/usr/sbin/dkms" "status" fi if [ -f /etc/sysconfig/isdncard ] ; then STATUS="Gathering information about ISDN:" catiffile "/etc/sysconfig/isdncard" fi STATUS="Collecting information from the proc directory:" catiffile "/proc/pci" STATUS="Getting kernel command line" catiffile "/proc/cmdline" STATUS="Gathering information about your CPU:" catiffile "/proc/cpuinfo" STATUS="Gathering information about your Ram:" catiffile "/proc/meminfo" STATUS="Gathering information about your ioports:" catiffile "/proc/ioports" STATUS="Gathering information about your interrupts:" catiffile "/proc/interrupts" STATUS="Gathering information about your scsi devices:" catiffile "/proc/scsi" STATUS="Gathering information about your dma:" catiffile "/proc/dma" STATUS="Gathering information about your devices (/proc/devices):" catiffile "/proc/devices" STATUS="Gathering information about your rtc:" catiffile "/proc/rtc" STATUS="Gathering information about your ide drivers:" catiffile "/proc/ide" if [ "$hardware" == "yes" ]; then STATUS="Gathering information about your bus:" catifexec "/usr/bin/lspci" catiffile "/proc/bus" fi echo echo "Getting disk and filesystem information." echo STATUS="Collecting information from /etc/fstab:" catiffile "/etc/fstab" STATUS="Collecting disk partition information:" catifexec "/sbin/fdisk" "-l" STATUS="Checking mounted file systems (mount) " catifexec "/bin/mount" STATUS="Checking mounted file systems (/proc/mounts)" catiffile "/proc/mounts" STATUS="Collecting Software RAID information (/proc/mdstat)" catiffile "/proc/mdstat" STATUS="Collecting Software RAID information (/etc/raidtab)" catiffile "/etc/raidtab" STATUS="Collecting Software RAID information (/etc/mdadm.conf)" catiffile "/etc/mdadm.conf" STATUS="Collecting Software RAID information (/sbin/mdadm -Q)" if ls /dev/md?* >/dev/null 2>&1; then catifexec "/sbin/mdadm" "-Q" "--detail" '/dev/md?*' fi STATUS="Collecting Automount information (auto.master)" catiffile "/etc/auto.master" STATUS="Collecting Automount information (auto.misc)" catiffile "/etc/auto.misc" STATUS="Collecting Automount information (auto.net)" catiffile "/etc/auto.net" STATUS="Collecting LVM information:" if [ $os = "redhat" ]; then catifexec "/usr/sbin/vgdisplay" "-vv" elif [ $os = "debian" ]; then catifexec "/sbin/vgdisplay" "-vv" fi STATUS="Collecting device-mapper (dm) information:" catifexec '/sbin/dmsetup' 'info' STATUS="Collecting SCSI Tape information (/etc/stinit.def)" catiffile "/etc/stinit.def" if [ -x /sbin/lsusb ] ; then STATUS="Collecting USB devices list (lsusb):" catifexec "/sbin/lsusb" fi if [ -x /usr/bin/lshal ] ; then STATUS="Collecting global devices list (lshal):" catifexec "/usr/bin/lshal" fi STATUS="Gathering information on SELinux setup" catifexec "/usr/bin/selinuxconfig" catifexec "/usr/sbin/sestatus" if [ $os = "redhat" ]; then catifexec "rpm" "-q -V selinux-policy-targeted" catifexec "rpm" "-q -V selinux-policy-strict" fi if [ $usevserver = yes ]; then STATUS="Gathering vserver information" catiffile "/proc/virtual" fi if [ "$partitions" == "yes" ]; then if [ "$dosfdisk" == "yes" ]; then if [ ! -x "$SFDISK" ]; then warning "can't find sfdisk, skipping sfdisk report." partitions="no" fi fi if [ "$dohwinfo" == "yes" ]; then if [ ! -x "$HWINFO" ]; then warning "can't find hwinfo, skipping partition report." partitions="no" fi fi fi if [ "$hardware" == "yes" ]; then if [ ! -x "$HWINFO" ]; then warning "can't find hwinfo, skipping hardware report." hardware="no" fi fi ## HARDWARE ############################# # # here we use hwinfo to dump a table listing all the # information we can find on the hardware of this machine # if [ "$hardware" == "yes" ]; then if [ "$dohwinfo" == "yes" ]; then if [ -f $hardwarefile ]; then rm $hardwarefile fi touch $hardwarefile echo -e "\n\n====================== summary ======================\n" >> $hardwarefile debug "$HWINFO --short --cpu --network --disk --pci >> $hardwarefile" $HWINFO --short --cpu --network --disk --pci >> $hardwarefile for flag in cpu network bios pci; do echo -e "\n\n====================== $flag ======================\n" >> $hardwarefile $HWINFO --$flag >> $hardwarefile done fi fi ## PARTITIONS ############################# # here we use sfdisk to dump a listing of all the partitions. # these files can be used to directly partition a disk of the same size. if [ "$partitions" == "yes" ]; then if [ "$dosfdisk" == "yes" ]; then devices=`LC_ALL=C $LSBLK --output NAME,TYPE --list --paths 2>/dev/null | grep "disk$" | @AWK@ '{print $1}'` if [ "$devices" == "" ]; then warning "No harddisks found" fi for dev in $devices; do debug "$SFDISK will try to backup partition tables for device $dev" [ -b $dev ] || continue label=${dev#/dev/} label=${label//\//-} outputfile=${partitionsfile//__star__/$label} debug "$SFDISK $sfdisk_options -d $dev > $outputfile 2>/dev/null" $SFDISK $sfdisk_options -d $dev > $outputfile 2>/dev/null if [ $? -ne 0 ]; then warning "The partition table for $dev could not be saved." fi done fi if [ "$dohwinfo" == "yes" ]; then debug "Using $HWINFO to get all available disk information" echo -e "\n\n====================== $disk ======================\n" >> $hardwarefile $HWINFO --disk >> $hardwarefile fi fi if [ "$luksheaders" == "yes" ]; then devices=`LC_ALL=C $SFDISK -l 2>/dev/null | grep "^Disk /dev" | @AWK@ '{print $2}' | cut -d: -f1` [ -n "$devices" ] || warning "No block device found" partitions=`LC_ALL=C $SFDISK -l 2>/dev/null |grep "^/dev" | @AWK@ '{print $1}'` [ -n "$partitions" ] || warning "No partitions found" targetdevices="" for dev in $devices $partitions; do [ -b $dev ] || continue debug "$CRYPTSETUP isLuks $dev" $CRYPTSETUP isLuks $dev [ $? -eq 0 ] && targetdevices="$targetdevices $dev" done for dev in $targetdevices; do label=${dev#/dev/} label=${label//\//-} outputfile=${luksheadersfile//__star__/$label} # the following sizes are expressed in terms of 512-byte sectors debug "Let us find out the LUKS header size for $dev" debug "$CRYPTSETUP luksDump \"$dev\" | grep '^Payload offset:' | @AWK@ '{print $3}'" headersize=`$CRYPTSETUP luksDump "$dev" | grep '^Payload offset:' | @AWK@ '{print $3}'` if [ $? -ne 0 ]; then warning "Could not compute the size of LUKS header, skipping $dev" continue elif [ -z "$headersize" -o -n "`echo \"$headersize\" | @SED@ 's/[0-9]*//g'`" ]; then warning "The computed size of LUKS header is not an integer, skipping $dev" continue fi debug "Let us backup the LUKS header of $dev" debug "$DD if=\"${dev}\" of=\"${outputfile}\" bs=512 count=\"${headersize}\"" output=`$DD if="${dev}" of="${outputfile}" bs=512 count="${headersize}" 2>&1` exit_code=$? if [ $exit_code -eq 0 ]; then debug "$output" info "The LUKS header of $dev was saved to $outputfile." else debug "$output" fatal "The LUKS header of $dev could not be saved." fi done fi if [ "$mbr" == "yes" ]; then devices=`LC_ALL=C $SFDISK -l 2>/dev/null | grep "^Disk /dev" | @AWK@ '{print $2}' | cut -d: -f1` if [ "$devices" == "" ]; then warning "No harddisks found" fi for dev in $devices; do debug "Will try to backup MBR tables for device $dev" [ -b $dev ] || continue label=${dev#/dev/} label=${label//\//-} outputfile=${mbrfile//__star__/$label} debug "$DD if=$dev of=$outputfile bs=512 count=1 2>/dev/null" $DD if=$dev of=$outputfile bs=512 count=1 2>/dev/null if [ $? -ne 0 ]; then warning "The MBR for $dev could not be saved." fi done fi ## LVM #################################### # returns 0 on success, 1 on error, 2 if not tried # outputs error message if error, reason if not tried function doLvmBackup () { local lvmdir="$1" if [ ! -d "$lvmdir" ]; then if ! mkdir "$lvmdir"; then echo "could not create $lvmdir" return 2 else info "successfully created $lvmdir" fi fi if [ ! -w "$lvmdir" ]; then echo "can not write to directory $lvmdir" return 2 fi debug "Let's try to gather the list of LVM volume groups" debug "$VGS --options vg_name --noheadings | @SED@ 's/^[ ]*//' | @SED@ 's/[ ]*$//' | tr '\n' ' '" vgs=`$VGS --options vg_name --noheadings | @SED@ 's/^[ ]*//' | @SED@ 's/[ ]*$//' | tr '\n' ' '` debug "Let's try to backup LVM metadata for detected volume groups: $vgs" for vg in $vgs do debug "$VGCFGBACKUP --file \"${lvmdir}\"/\'%s\' $vg" output=`$VGCFGBACKUP --file "${lvmdir}"/'%s' $vg` done exit_code=$? debug "$output" case $exit_code in 0) info "LVM metadata was saved to $lvmdir for volume groups: $vgs" return 0 ;; *) echo "LVM metadata could not be saved for at least one of these volume groups: $vgs" return 1 ;; esac } if [ "$lvm" == "yes" ]; then output=`doLvmBackup "${parentdir}/lvm"` exit_code=$? case $exit_code in 0) # success. info message has already been displayed true ;; 1) # error fatal "$output" ;; 2) # could not even try fatal "LVM metadata backup was not tried: $output" ;; *) # should never happen fatal "Unhandled error ($exit_code) while trying to backup LVM metadata, please report a bug" ;; esac fi ## BIOS #################################### if [ "$bios" == "yes" ]; then debug "Trying to backup BIOS" debug "$FLASHROM -r ${parentdir}/bios --programmer internal >/dev/null 2>&1" $FLASHROM -r ${parentdir}/bios --programmer internal >/dev/null 2>&1 if [ $? -ne 0 ]; then warning "The BIOS could not be saved." fi fi