Fix formating of disk tools output
[grml-hwinfo.git] / grml-hwinfo
index 7ca5c18..a58e829 100755 (executable)
@@ -1,10 +1,9 @@
-#!/bin/sh
+#!/bin/bash
 # Filename:      grml-hwinfo
 # Purpose:       get hardware information
 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
 # Bug-Reports:   see http://grml.org/bugs/
 # License:       This file is licensed under the GPL v2.
-# Latest change: Mon Jun 11 12:15:04 CEST 2007 [mika]
 ################################################################################
 # Notice: Some ideas have been taken from
 # http://club.black.co.at/david/hwdb/infodump
 # variables
 UNAME="$(uname -r)"
 PN="$(basename $0)"
-VERSION='0.3'
+[ -n "$WORKING_DIR" -a -d "$WORKING_DIR" ] || WORKING_DIR=$(pwd)
+VERSION='***UNRELEASED***'
 
-[ -n "$INFOFILE" ] || INFOFILE='info.tar.bz2'
+# 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)"
 
-if [ "$(id -u)" != 0 ] ; then
+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 this tool is being executed
+on.  It can be executed as normal user to collect some basic information or
+with root permissions to collect as much information as possible.  By
+default, a file named grml-hwinfo-TIMESTAMP.tar.bz2 storing all collected
+information will be created in the current working directory. Alternatively,
+you can have it create a directory with all information.
+
+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 <dir>   Store output files in specified directory
+  --output-file <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 "Notice: you are running $PN without root permissions. Not all information will be collected."
-   echo
+   echo "W: Running without root permissions. Not all data will be collected."
 fi
 
 # check whether a binary is available and executable
@@ -30,8 +121,13 @@ exectest() {
 if [ -z "$1" ] ; then
    echo 'Usage: exectest <binary>'>&2
    return 1
-else 
-   test -e "$(which $1)" && return 0 || 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
 }
 
@@ -67,15 +163,12 @@ disk_info() {
     disklist=`list_disks $device_size`
 }
 
-echo "Running grml-hwinfo ${VERSION} - collecting hardware information."
-echo "Please send feedback, bugreports, feature requests to Michael Prokop <mika@grml.org>."
-echo ""
 
-mkdir info || exit -1
+cd "${OUTDIR}" || exit 1
 (
-  cd info
-
-  echo "Generating hardware information report using file $INFOFILE."
+  [ -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
@@ -99,6 +192,7 @@ mkdir info || exit -1
   for i in free lsmod mount lsdev ; 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 \
@@ -114,6 +208,8 @@ mkdir info || exit -1
 # 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
 
 # net stuff
   exectest ifconfig  && ifconfig -v -a  > ifconfig
@@ -125,14 +221,13 @@ mkdir info || exit -1
   if exectest dpkg ; then
      dpkg --get-selections   > dpkg_get_selections
      COLUMNS=300 dpkg --list > dpkg_list
-     COLUMNS=1000 dpkg -l linux-image-$UNAME | grep linux-image-$UNAME | tr -s ' ' > running_kernel
   fi
 
-# powermanagement
-  exectest laptop-detect  && laptop-detect 1>/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 > acpi
+# 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
@@ -141,13 +236,17 @@ mkdir info || exit -1
      [ -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        1> x_version 2>&1
+     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
@@ -168,32 +267,92 @@ else
    echo "running as root" > root
    disk_info
    exectest sfdisk     && sfdisk -d > sfdisk 2>sfdisk.error
-   exectest ddcprobe   && ddcprobe  > ddcprobe
    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
+
    for disk in $disklist; do
-      exectest smartctl  && smartctl -i /dev/$disk >> smartctl
-      exectest hdparm    && hdparm -iv /dev/$disk  >> hdparm
-      exectest fdisk     && fdisk -lu /dev/$disk   >> fdisk 2>>fdisk.error
-      exectest parted    && parted -s /dev/$disk print >> parted
-      LC_ALL=C file -s /dev/$disk?* | grep -v ": empty" >> file_disk
+     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
 )
 
-# finally create the tarball
-if [ -f "$INFOFILE" ] ; then
-   DATE="$(date +%Y%m%d_%H%M%S)"
-   NEW_INFOFILE="info_$DATE.tar.bz2"
-   echo
-   echo "Warning:  $INFOFILE exists already, using $NEW_INFOFILE instead.">&2
-   tar jcf $NEW_INFOFILE info/ && rm -Rf info/
-   INFOFILE="$NEW_INFOFILE" # adjust variable for final info message
+# get rid of empty files
+for file in *; do
+  test -s $file || rm $file
+done
+
+echo
+
+cd "${WORKING_DIR}"
+
+# create tarball
+if [ -n "$GENERATE_FILE" ] ; then
+  tar jcf "${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
-   tar jcf $INFOFILE info/ && rm -Rf info/
+  [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
 fi
 
-echo
-[ -r "$INFOFILE" ] && echo "$INFOFILE ($(ls -ahl $INFOFILE | awk '{print $5}')) has been generated."
-echo
+exit 0
 
 ## END OF FILE##################################################################