Rework cmdline option handling, replacing "-df" with "-b" and adding new options
[grml-hwinfo.git] / grml-hwinfo
1 #!/bin/bash
2 # Filename:      grml-hwinfo
3 # Purpose:       get hardware information
4 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 ################################################################################
8 # Notice: Some ideas have been taken from
9 # http://club.black.co.at/david/hwdb/infodump
10 # by David Schmitt <david@schmitt.edv-bus.at>
11 ################################################################################
12
13 # variables
14 UNAME="$(uname -r)"
15 PN="$(basename $0)"
16 [ -n "$WORKING_DIR" -a -d "$WORKING_DIR" ] || WORKING_DIR=$(pwd)
17 VERSION='***UNRELEASED***'
18
19 # data collection should not be affected by user locale
20 export LANG=C
21 export LC_ALL=C
22
23 TIMESTAMP='+%F--%H-%M-%S-%Z'
24 DATE="$(date $TIMESTAMP)"
25
26 echo "$PN ${VERSION} - collect hardware information"
27
28 # defaults
29 GENERATE_FILE='1'
30 GENERATE_DIRECTORY=''
31 _opt_output_directory=false
32 _opt_output_file=false
33
34 usage() {
35   echo "
36 This tool collects information of the hardware this tool is being executed
37 on.  It can be executed as normal user to collect some basic information or
38 with root permissions to collect as much information as possible.  By
39 default, a file named grml-hwinfo-TIMESTAMP.tar.bz2 storing all collected
40 information will be created in the current working directory. Alternatively,
41 you can have it create a directory with all information.
42
43 Options:
44
45   -b, --both                 Create directory + file grml-hwinfo-TIMESTAMP.tar.bz2
46   -d, --directory            Create grml-hwinfo-TIMESTAMP as a directory (no file)
47   -f, --file                 Create grml-hwinfo-TIMESTAMP.tar.bz2 [default action]
48   -h, --help                 Display this help message
49   --output-directory <dir>   Store output files in specified directory
50   --output-file <file>       Store output in specified filename (tar.bz2 format)
51 "
52 }
53
54 CMDLINE_OPTS=output-directory:,output-file:,both,directory,file,help
55 _opt_temp=$(getopt --name grml-hwinfo -o +bdfh --long $CMDLINE_OPTS -- "$@")
56 if [ $? -ne 0 ]; then
57   echo "Try 'grml-hwinfo --help' for more information." >&2
58   exit 1
59 fi
60 eval set -- "$_opt_temp"
61
62 while :; do
63   case "$1" in
64   --help|-h)
65     usage ; exit 0
66     ;;
67   --output-directory)
68     shift; OUTDIRNAME="$1"
69     GENERATE_DIRECTORY='1'
70     _opt_output_directory=true
71     $_opt_output_file && GENERATE_FILE='1' || GENERATE_FILE=''
72     ;;
73   --output-file)
74     shift; OUTFILE="$1"
75     GENERATE_FILE='1'
76     _opt_output_file=true
77     $_opt_output_directory && GENERATE_DIRECTORY='1' || GENERATE_DIRECTORY=''
78     ;;
79   -d|--directory)
80     GENERATE_DIRECTORY='1'
81     GENERATE_FILE=''
82     ;;
83   -f|--file)
84     GENERATE_DIRECTORY=''
85     GENERATE_FILE='1'
86     ;;
87   -b|--both)
88     GENERATE_DIRECTORY='1'
89     GENERATE_FILE='1'
90     ;;
91   --)
92     shift; break
93     ;;
94   *)
95     echo "Internal getopt error!" >&2
96     exit 1
97     ;;
98   esac
99   shift
100 done
101
102 # Generate output/temporary directory name & path, and output file path
103 [ -n "$OUTDIRNAME" ] || OUTDIRNAME="grml-hwinfo-${DATE}"
104 OUTDIR="${WORKING_DIR}/${OUTDIRNAME}"
105 mkdir "${OUTDIR}" || { echo 'Directory "'${OUTDIR}'" already exists, aborting.'>&2 ; exit 1; }
106
107 if [ -n "$GENERATE_FILE" ] ; then
108    [ -n "$OUTFILE" ] && OUTFILE_="$OUTFILE" || OUTFILE_="${OUTDIR}.tar.bz2"
109    [ -e "${OUTFILE_}" ] && { echo 'File "'${OUTFILE_}'" already exists, aborting.'>&2 ; rm -r "${OUTDIR}"; exit 1; }
110    OUTFILE=${OUTFILE_}
111    touch "${OUTFILE}"
112 fi
113
114 if [ "$(id -u)" != "0" ] ; then
115    NOTROOT=1
116    echo "W: Running without root permissions. Not all data will be collected."
117 fi
118
119 # check whether a binary is available and executable
120 exectest() {
121 if [ -z "$1" ] ; then
122    echo 'Usage: exectest <binary>'>&2
123    return 1
124 else
125    if test -e "$(which $1)" ; then
126      return 0
127    else
128      grep -q "^$1"'$' missing_tools 2>/dev/null || echo "$1" >> missing_tools
129      return 1
130    fi
131 fi
132 }
133
134 # echo a list of all disks and their size
135 # taken from http://cvs.debian.org/fai/lib/disk-info
136 diskandsize() {
137     local isdisk major minor blocks device suffix
138     while read major minor blocks device suffix; do
139         isdisk=1
140         # skip ide cdrom
141         [ -f /proc/ide/$device/media ] && grep -q cdrom /proc/ide/$device/media && isdisk=0
142         [ "$isdisk" -eq 1 ] && echo "$device $blocks"
143     done
144 }
145
146 list_disks() {
147 # print only every second entry; used by disk_info
148 i=0
149 for ent in $@; do
150     if [ "$i" -eq 0 ]; then
151         echo $ent
152         i=1
153     else
154         i=0
155     fi
156 done
157 }
158
159 disk_info() {
160     # the variable holds a space separated list of devices and their block size
161     device_size=`grep -E ' cciss/c.d.$| ida/c.d.$| rd/c.d.$| hd.$| sd.$|/disc$' /proc/partitions | diskandsize`
162     # a list of all local disks, without size
163     disklist=`list_disks $device_size`
164 }
165
166
167 cd "${OUTDIR}" || exit 1
168 (
169   [ -n "$GENERATE_FILE" ]      && echo "Output file:      $OUTFILE"
170   [ -n "$GENERATE_DIRECTORY" ] && echo "Output directory: $OUTDIR"
171   echo
172   echo "This might take a few seconds/minutes. Please be patient..."
173
174 # some sysinfo
175   date > date
176   if [ -r /etc/grml_version ] ; then
177      cat /etc/grml_version > grml_version
178   fi
179   if [ -r /etc/debian_version ] ; then
180      cat /etc/debian_version > debian_version
181   fi
182   uname -a > uname
183
184 # disks / devices
185   [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi
186   (lspci; lspci -n) | sort > lspci
187   [ -r /proc/bus/pnp ] && lspnp > lspnp
188   [ -r /proc/bus/usb ] && lsusb > lsusb
189   cat /proc/partitions > partitions
190   find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
191   df -h > df 2>/dev/null
192   for i in free lsmod mount lsdev ; do
193       exectest $i  && $i > $i
194   done
195   swapon -s > swapon 2>swapon.error
196
197 # proc stuff
198   for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
199     mdstat meminfo modules mtrr pci version ; do
200     [ -r /proc/$i ] && cat /proc/$i > proc_$i
201   done
202   exectest sysdump  && sysdump > sysdump 2>sysdump.error
203 # for sysnet in `find /proc/sys/net/*/ -type f | grep -v flush`; do cat $sysnet >> sysnet ; done
204
205 # log
206   dmesg > dmesg.cur
207
208 # hwinfo
209   exectest discover && discover -v --type-summary --enable-bus all > discover 2> discover.2
210   exectest hwinfo   && hwinfo log=hwinfo
211   exectest numactl  && numactl --hardware > numactl
212   exectest x86info  && x86info > x86info 2>x86info.2
213
214 # net stuff
215   exectest ifconfig  && ifconfig -v -a  > ifconfig
216   exectest ip        && ip route show   > ip_route
217   exectest ip        && ip link show    > ip_link
218   exectest route     && route -n        > route
219
220 # software
221   if exectest dpkg ; then
222      dpkg --get-selections   > dpkg_get_selections
223      COLUMNS=300 dpkg --list > dpkg_list
224   fi
225
226 # power management
227   exectest laptop-detect  && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
228   exectest acpi_available && acpi_available && cat /proc/acpi/info > acpi_info
229   exectest acpi && acpi > acpi 2> acpi.error && acpi -v > acpi.version
230   [ -r /proc/apm/ ] && apm > apm
231
232 # kernel stuff
233   if [ -r /proc/config.gz ] ; then
234      zcat /proc/config.gz > kernelconfig
235   else
236      [ -r /boot/config-$UNAME ] && cat /boot/config-$UNAME > kernelconfig
237   fi
238
239   exectest dpkg && COLUMNS=1000 dpkg -l linux-image-$UNAME 2>running_kernel.error \
240            | grep linux-image-$UNAME | tr -s ' ' > running_kernel 2>>running_kernel.error
241   dpkg -S /boot/vmlinuz-$(uname -r) >> running_kernel 2>>running_kernel.error
242
243 # X stuff
244   if [ -n "${DISPLAY}" ] ; then
245      exectest xviddetect  && xviddetect         > xviddetect
246      exectest xvidtune    && xvidtune -show     > xdivtune
247      exectest xrandr      && xrandr             > xrandr
248      exectest xdpyinfo    && xdpyinfo           > xdpyinfo
249      X -version > x_version 2>&1
250   fi
251
252   for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
253       cp /var/log/$i log_$i 2>/dev/null
254   done
255
256   cp /etc/X11/xorg.conf    xorg.conf    2>/dev/null
257   cp /etc/modules          modules      2>/dev/null
258   cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
259
260 # not available:
261 # sysinfo -class device -level all
262
263 # as root:
264 if [ -n "$NOTROOT" ] ; then
265    echo "not running as root" > root
266 else
267    echo "running as root" > root
268    disk_info
269    exectest sfdisk     && sfdisk -d > sfdisk 2>sfdisk.error
270    exectest dmidecode  && dmidecode > dmidecode
271
272    exectest dconf && dconf -o dconf
273
274    if [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
275       /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
276    fi
277
278    exectest mdadm && mdadm --detail /dev/md[0-9]* >> mdadm 2>mdadm.error
279
280    # LVM
281    exectest pvs && pvs > pvs 2>pvs.error
282    exectest vgs && vgs > vgs 2>vgs.error
283    exectest lvs && lvs > lvs 2>lvs.error
284    exectest lvdisplay && lvdisplay > lvdisplay 2>lvdisplay.error
285
286    exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
287
288    for disk in $disklist; do
289       exectest smartctl  && echo "smartctl -a /dev/$disk :\n" >> smartctl && smartctl -a /dev/$disk       >> smartctl             && echo "\n\n" >> smartctl
290       exectest hdparm    && echo "hdparm -iv  /dev/$disk :\n" >> hdparm   && hdparm -iv  /dev/$disk       >> hdparm               && echo "\n\n" >> hdparm
291       exectest fdisk     && echo "fdisk -lu   /dev/$disk :\n" >> fdisk    && fdisk -lu   /dev/$disk       >> fdisk 2>>fdisk.error && echo "\n\n" >> fdisk
292       exectest parted    && echo "parted -s   /dev/$disk :\n" >> parted   && parted -s   /dev/$disk print >> parted               && echo "\n\n" >> parted
293       file -s /dev/$disk?* | grep -v ": empty" >> file_disk
294    done
295 fi
296 )
297
298 # get rid of empty files
299 for file in *; do
300   test -s $file || rm $file
301 done
302
303 echo
304
305 cd "${WORKING_DIR}"
306
307 # create tarball
308 if [ -n "$GENERATE_FILE" ] ; then
309   tar jcf "${OUTFILE}" "${OUTDIRNAME}"
310   [ -r "$OUTFILE" ] && echo "$OUTFILE ("$(ls -ahl "$OUTFILE" | awk '{print $5}')") has been generated."
311 fi
312
313 # remove (temporary) output directory if needed, else keep it, as it doubles
314 # as the real output directory.
315 if [ -z "$GENERATE_DIRECTORY" ] ; then
316   rm -r "${OUTDIR}"
317 else
318   [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
319 fi
320
321 exit 0
322
323 ## END OF FILE##################################################################