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