#!/bin/bash # Filename: grml-hwinfo # Purpose: get hardware information # Authors: grml-team (grml.org), (c) Michael Prokop # Bug-Reports: see http://grml.org/bugs/ # License: This file is licensed under the GPL v2. ################################################################################ # Notice: Some ideas have been taken from # http://club.black.co.at/david/hwdb/infodump # by David Schmitt ################################################################################ # variables UNAME="$(uname -r)" PN="$(basename $0)" [ -n "$WORKING_DIR" -a -d "$WORKING_DIR" ] || WORKING_DIR=$(pwd) VERSION='***UNRELEASED***' # data collection should not be affected by user locale export LANG=C export LC_ALL=C TIMESTAMP='+%F--%H-%M-%S-%Z' DATE="$(date $TIMESTAMP)" echo "$PN ${VERSION} - collect hardware information" # defaults GENERATE_FILE='1' GENERATE_DIRECTORY='' _opt_output_directory=false _opt_output_file=false usage() { echo " This tool collects information of the hardware it is being executed on. It can be executed as normal user to collect some basic information or (recommended) with root permissions to collect more system information. If executed without any options a file named grml-hwinfo-TIMESTAMP.tar.bz2 storing all collected information is created in the current working directory. Options: -b, --both Create directory + file grml-hwinfo-TIMESTAMP.tar.bz2 -d, --directory Create grml-hwinfo-TIMESTAMP as a directory (no file) -f, --file Create grml-hwinfo-TIMESTAMP.tar.bz2 [default action] -h, --help Display this help message --output-directory Store output files in specified directory --output-file Store output in specified filename (tar.bz2 format) " } CMDLINE_OPTS=output-directory:,output-file:,both,directory,file,help _opt_temp=$(getopt --name grml-hwinfo -o +bdfh --long $CMDLINE_OPTS -- "$@") if [ $? -ne 0 ]; then echo "Try 'grml-hwinfo --help' for more information." >&2 exit 1 fi eval set -- "$_opt_temp" while :; do case "$1" in --help|-h) usage ; exit 0 ;; --output-directory) shift; OUTDIRNAME="$1" GENERATE_DIRECTORY='1' _opt_output_directory=true $_opt_output_file && GENERATE_FILE='1' || GENERATE_FILE='' ;; --output-file) shift; OUTFILE="$1" GENERATE_FILE='1' _opt_output_file=true $_opt_output_directory && GENERATE_DIRECTORY='1' || GENERATE_DIRECTORY='' ;; -d|--directory) GENERATE_DIRECTORY='1' GENERATE_FILE='' ;; -f|--file) GENERATE_DIRECTORY='' GENERATE_FILE='1' ;; -b|--both) GENERATE_DIRECTORY='1' GENERATE_FILE='1' ;; --) shift; break ;; *) echo "Internal getopt error!" >&2 exit 1 ;; esac shift done # Generate output/temporary directory name & path, and output file path [ -n "$OUTDIRNAME" ] || OUTDIRNAME="grml-hwinfo-${DATE}" OUTDIR="${WORKING_DIR}/${OUTDIRNAME}" mkdir "${OUTDIR}" || { echo 'Directory "'${OUTDIR}'" already exists, aborting.'>&2 ; exit 1; } if [ -n "$GENERATE_FILE" ] ; then [ -n "$OUTFILE" ] && OUTFILE_="$OUTFILE" || OUTFILE_="${OUTDIR}.tar.bz2" [ -e "${OUTFILE_}" ] && { echo 'File "'${OUTFILE_}'" already exists, aborting.'>&2 ; rm -r "${OUTDIR}"; exit 1; } OUTFILE=${OUTFILE_} touch "${OUTFILE}" fi if [ "$(id -u)" != "0" ] ; then NOTROOT=1 echo "W: Running without root permissions. Not all data will be collected." fi # check whether a binary is available and executable exectest() { if [ -z "$1" ] ; then echo 'Usage: exectest '>&2 return 1 else if test -e "$(which $1)" ; then return 0 else grep -q "^$1"'$' missing_tools 2>/dev/null || echo "$1" >> missing_tools return 1 fi fi } # echo a list of all disks and their size # taken from http://cvs.debian.org/fai/lib/disk-info diskandsize() { local isdisk major minor blocks device suffix while read major minor blocks device suffix; do isdisk=1 # skip ide cdrom [ -f /proc/ide/$device/media ] && grep -q cdrom /proc/ide/$device/media && isdisk=0 [ "$isdisk" -eq 1 ] && echo "$device $blocks" done } list_disks() { # print only every second entry; used by disk_info i=0 for ent in $@; do if [ "$i" -eq 0 ]; then echo $ent i=1 else i=0 fi done } disk_info() { # the variable holds a space separated list of devices and their block size device_size=`grep -E ' cciss/c.d.$| ida/c.d.$| rd/c.d.$| hd.$| sd.$|/disc$' /proc/partitions | diskandsize` # a list of all local disks, without size disklist=`list_disks $device_size` } cd "${OUTDIR}" || exit 1 ( [ -n "$GENERATE_FILE" ] && echo "Output file: $OUTFILE" [ -n "$GENERATE_DIRECTORY" ] && echo "Output directory: $OUTDIR" echo echo "This might take a few seconds/minutes. Please be patient..." # some sysinfo date > date if [ -r /etc/grml_version ] ; then cat /etc/grml_version > grml_version fi if [ -r /etc/debian_version ] ; then cat /etc/debian_version > debian_version fi uname -a > uname # disks / devices [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi exectest lspci && lspci -nn > lspci cat /proc/partitions > partitions find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null df -h > df 2>/dev/null for i in free lsmod mount lsdev lspnp lsusb ; do exectest $i && $i > $i done swapon -s > swapon 2>swapon.error # proc stuff for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \ mdstat meminfo modules mtrr pci version ; do [ -r /proc/$i ] && cat /proc/$i > proc_$i done exectest sysdump && sysdump > sysdump 2>sysdump.error # log dmesg > dmesg.cur # hwinfo exectest discover && discover -v --type-summary --enable-bus all > discover 2> discover.2 exectest hwinfo && hwinfo log=hwinfo exectest numactl && numactl --hardware > numactl exectest x86info && x86info > x86info 2>x86info.2 exectest lscpu && lscpu > lscpu # net stuff exectest ifconfig && ifconfig -v -a > ifconfig exectest ip && ip route show > ip_route exectest ip && ip link show > ip_link exectest route && route -n > route # software if exectest dpkg ; then dpkg --get-selections > dpkg_get_selections COLUMNS=300 dpkg --list > dpkg_list fi # power management exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected exectest acpi_available && acpi_available && cat /proc/acpi/info > acpi_info exectest acpi && acpi > acpi 2> acpi.error && acpi -v > acpi.version [ -r /proc/apm/ ] && apm > apm # kernel stuff if [ -r /proc/config.gz ] ; then zcat /proc/config.gz > kernelconfig else [ -r /boot/config-$UNAME ] && cat /boot/config-$UNAME > kernelconfig fi exectest dpkg && COLUMNS=1000 dpkg -l linux-image-$UNAME 2>running_kernel.error \ | grep linux-image-$UNAME | tr -s ' ' > running_kernel 2>>running_kernel.error dpkg -S /boot/vmlinuz-$(uname -r) >> running_kernel 2>>running_kernel.error # X stuff if [ -n "${DISPLAY}" ] ; then exectest xviddetect && xviddetect > xviddetect exectest xvidtune && xvidtune -show > xdivtune exectest xrandr && xrandr > xrandr exectest xdpyinfo && xdpyinfo > xdpyinfo X -version > x_version 2>&1 fi for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do cp /var/log/$i log_$i 2>/dev/null done cp /etc/X11/xorg.conf xorg.conf 2>/dev/null cp /etc/modules modules 2>/dev/null cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null # as root: if [ -n "$NOTROOT" ] ; then echo "not running as root" > root else echo "running as root" > root disk_info exectest sfdisk && sfdisk -d > sfdisk 2>sfdisk.error exectest dmidecode && dmidecode > dmidecode exectest dconf && dconf -o dconf if [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error fi # proxmox exectest qm && qm list > qm 2>qm.error # libvirt exectest virsh && virsh list >virsh 2>virsh.error # openvz exectest vzlist && vzlist >vzlist 2>vzlist.error # vserver exectest vserver-stat && vserver-stat >vserver-stat 2>vserver-stat.error exectest mdadm && mdadm --detail /dev/md[0-9]* >> mdadm 2>mdadm.error # LVM exectest pvs && pvs > pvs 2>pvs.error exectest vgs && vgs > vgs 2>vgs.error exectest lvs && lvs > lvs 2>lvs.error exectest lvdisplay && lvdisplay > lvdisplay 2>lvdisplay.error exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error exectest lsblk && lsblk > lsblk 2>lsblk.error # iSCSI if exectest iscsiadm ; then iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error fi if exectest lsscsi ; then lsscsi > lsscsi 2>lsscsi.error lsscsi -t > lsscsi_transport 2>lsscsi_transport.error fi for disk in $disklist; do if exectest smartctl ; then echo -e "smartctl -a /dev/${disk}:\n" >> smartctl smartctl -a /dev/$disk >> smartctl echo -e "\n\n" >> smartctl fi if exectest hdparm ; then echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm hdparm -iv /dev/$disk >> hdparm echo -e "\n\n" >> hdparm fi if exectest fdisk ; then echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk fdisk -lu /dev/$disk >>fdisk 2>>fdisk.error echo -e "\n\n" >> fdisk fi if exectest parted ; then echo -e "parted -s /dev/${disk}:\n" >> parted parted -s /dev/$disk print >> parted echo -e "\n\n" >> parted fi if exectest sdparm ; then echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm sdparm --all --long /dev/$disk >> sdparm echo -e "\n\n" >> sdparm fi file -s /dev/$disk?* | grep -v ": empty" >> file_disk done fi ) # get rid of empty files for file in *.error ; do test -s $file || rm $file done echo cd "${WORKING_DIR}" # create tarball if [ -n "$GENERATE_FILE" ] ; then tar acf "${OUTFILE}" "${OUTDIRNAME}" [ -r "$OUTFILE" ] && echo "$OUTFILE ("$(ls -ahl "$OUTFILE" | awk '{print $5}')") has been generated." fi # remove (temporary) output directory if needed, else keep it, as it doubles # as the real output directory. if [ -z "$GENERATE_DIRECTORY" ] ; then rm -r "${OUTDIR}" else [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated." fi exit 0 ## END OF FILE##################################################################