Remove only empty *.error files to see which commands have been executed
[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   exectest lspci && lspci -nn > lspci
187   cat /proc/partitions > partitions
188   find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
189   df -h > df 2>/dev/null
190   for i in free lsmod mount lsdev lspnp lsusb ; do
191     exectest $i && $i > $i
192   done
193   swapon -s > swapon 2>swapon.error
194
195   # proc stuff
196   for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
197     mdstat meminfo modules mtrr pci version ; do
198     [ -r /proc/$i ] && cat /proc/$i > proc_$i
199   done
200   exectest sysdump  && sysdump > sysdump 2>sysdump.error
201
202   # log
203   dmesg > dmesg.cur
204
205   # hwinfo
206   exectest discover && discover -v --type-summary --enable-bus all > discover 2> discover.2
207   exectest hwinfo   && hwinfo log=hwinfo
208   exectest numactl  && numactl --hardware > numactl
209   exectest x86info  && x86info > x86info 2>x86info.2
210
211   # net stuff
212   exectest ifconfig  && ifconfig -v -a  > ifconfig
213   exectest ip        && ip route show   > ip_route
214   exectest ip        && ip link show    > ip_link
215   exectest route     && route -n        > route
216
217   # software
218   if exectest dpkg ; then
219     dpkg --get-selections   > dpkg_get_selections
220     COLUMNS=300 dpkg --list > dpkg_list
221   fi
222
223   # power management
224   exectest laptop-detect  && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
225   exectest acpi_available && acpi_available && cat /proc/acpi/info > acpi_info
226   exectest acpi && acpi > acpi 2> acpi.error && acpi -v > acpi.version
227   [ -r /proc/apm/ ] && apm > apm
228
229   # kernel stuff
230   if [ -r /proc/config.gz ] ; then
231     zcat /proc/config.gz > kernelconfig
232   else
233     [ -r /boot/config-$UNAME ] && cat /boot/config-$UNAME > kernelconfig
234   fi
235
236   exectest dpkg && COLUMNS=1000 dpkg -l linux-image-$UNAME 2>running_kernel.error \
237            | grep linux-image-$UNAME | tr -s ' ' > running_kernel 2>>running_kernel.error
238   dpkg -S /boot/vmlinuz-$(uname -r) >> running_kernel 2>>running_kernel.error
239
240   # X stuff
241   if [ -n "${DISPLAY}" ] ; then
242     exectest xviddetect  && xviddetect         > xviddetect
243     exectest xvidtune    && xvidtune -show     > xdivtune
244     exectest xrandr      && xrandr             > xrandr
245     exectest xdpyinfo    && xdpyinfo           > xdpyinfo
246     X -version > x_version 2>&1
247   fi
248
249   for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
250     cp /var/log/$i log_$i 2>/dev/null
251   done
252
253   cp /etc/X11/xorg.conf    xorg.conf    2>/dev/null
254   cp /etc/modules          modules      2>/dev/null
255   cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
256
257   # as root:
258   if [ -n "$NOTROOT" ] ; then
259     echo "not running as root" > root
260   else
261     echo "running as root" > root
262     disk_info
263     exectest sfdisk     && sfdisk -d > sfdisk 2>sfdisk.error
264     exectest dmidecode  && dmidecode > dmidecode
265
266     exectest dconf && dconf -o dconf
267
268     if [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
269       /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
270     fi
271
272     # proxmox
273     exectest qm && qm list > qm 2>qm.error
274     # libvirt
275     exectest virsh && virsh list >virsh 2>virsh.error
276     # openvz
277     exectest vzlist && vzlist >vzlist 2>vzlist.error
278     # vserver
279     exectest vserver-stat && vserver-stat >vserver-stat 2>vserver-stat.error
280
281     exectest mdadm && mdadm --detail /dev/md[0-9]* >> mdadm 2>mdadm.error
282
283     # LVM
284     exectest pvs && pvs > pvs 2>pvs.error
285     exectest vgs && vgs > vgs 2>vgs.error
286     exectest lvs && lvs > lvs 2>lvs.error
287     exectest lvdisplay && lvdisplay > lvdisplay 2>lvdisplay.error
288
289     exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
290
291     for disk in $disklist; do
292       if exectest smartctl ; then
293         echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
294         smartctl -a /dev/$disk >> smartctl
295         echo -e "\n\n" >> smartctl
296       fi
297
298       if exectest hdparm ; then
299         echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
300         hdparm -iv /dev/$disk >> hdparm
301         echo -e "\n\n" >> hdparm
302       fi
303
304       if exectest fdisk ; then
305         echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
306         fdisk -lu /dev/$disk >>fdisk 2>>fdisk.error
307         echo -e "\n\n" >> fdisk
308       fi
309
310       if exectest parted ; then
311         echo -e "parted -s /dev/${disk}:\n" >> parted
312         parted -s /dev/$disk print >> parted
313         echo -e "\n\n" >> parted
314       fi
315
316       if exectest sdparm ; then
317         echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
318         sdparm --all --long /dev/$disk >> sdparm
319         echo -e "\n\n" >> sdparm
320       fi
321
322       file -s /dev/$disk?* | grep -v ": empty" >> file_disk
323     done
324   fi
325 )
326
327 # get rid of empty files
328 for file in *.error ; do
329   test -s $file || rm $file
330 done
331
332 echo
333
334 cd "${WORKING_DIR}"
335
336 # create tarball
337 if [ -n "$GENERATE_FILE" ] ; then
338   tar jcf "${OUTFILE}" "${OUTDIRNAME}"
339   [ -r "$OUTFILE" ] && echo "$OUTFILE ("$(ls -ahl "$OUTFILE" | awk '{print $5}')") has been generated."
340 fi
341
342 # remove (temporary) output directory if needed, else keep it, as it doubles
343 # as the real output directory.
344 if [ -z "$GENERATE_DIRECTORY" ] ; then
345   rm -r "${OUTDIR}"
346 else
347   [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
348 fi
349
350 exit 0
351
352 ## END OF FILE##################################################################