ip: also store table specific route information
[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 it is being executed on.
37   It can be executed as normal user to collect some basic information or
38   (recommended) with root permissions to collect more system information.
39   If executed without any options a file named grml-hwinfo-TIMESTAMP.tar.bz2
40   storing all collected information is created in the current working directory.
41
42   Options:
43
44   -b, --both                 Create directory + file grml-hwinfo-TIMESTAMP.tar.bz2
45   -d, --directory            Create grml-hwinfo-TIMESTAMP as a directory (no file)
46   -f, --file                 Create grml-hwinfo-TIMESTAMP.tar.bz2 [default action]
47   -h, --help                 Display this help message
48   --output-directory <dir>   Store output files in specified directory
49   --output-file <file>       Store output in specified filename (tar.bz2 format)
50   "
51 }
52
53 CMDLINE_OPTS=output-directory:,output-file:,both,directory,file,help
54 _opt_temp=$(getopt --name grml-hwinfo -o +bdfh --long $CMDLINE_OPTS -- "$@")
55 if [ $? -ne 0 ]; then
56   echo "Try 'grml-hwinfo --help' for more information." >&2
57   exit 1
58 fi
59 eval set -- "$_opt_temp"
60
61 while :; do
62   case "$1" in
63   --help|-h)
64     usage ; exit 0
65     ;;
66   --output-directory)
67     shift; OUTDIRNAME="$1"
68     GENERATE_DIRECTORY='1'
69     _opt_output_directory=true
70     $_opt_output_file && GENERATE_FILE='1' || GENERATE_FILE=''
71     ;;
72   --output-file)
73     shift; OUTFILE="$1"
74     GENERATE_FILE='1'
75     _opt_output_file=true
76     $_opt_output_directory && GENERATE_DIRECTORY='1' || GENERATE_DIRECTORY=''
77     ;;
78   -d|--directory)
79     GENERATE_DIRECTORY='1'
80     GENERATE_FILE=''
81     ;;
82   -f|--file)
83     GENERATE_DIRECTORY=''
84     GENERATE_FILE='1'
85     ;;
86   -b|--both)
87     GENERATE_DIRECTORY='1'
88     GENERATE_FILE='1'
89     ;;
90   --)
91     shift; break
92     ;;
93   *)
94     echo "Internal getopt error!" >&2
95     exit 1
96     ;;
97   esac
98   shift
99 done
100
101 # Generate output/temporary directory name & path, and output file path
102 [ -n "$OUTDIRNAME" ] || OUTDIRNAME="grml-hwinfo-${DATE}"
103 OUTDIR="${WORKING_DIR}/${OUTDIRNAME}"
104 mkdir "${OUTDIR}" || { echo 'Directory "'${OUTDIR}'" already exists, aborting.'>&2 ; exit 1; }
105
106 if [ -n "$GENERATE_FILE" ] ; then
107   [ -n "$OUTFILE" ] && OUTFILE_="$OUTFILE" || OUTFILE_="${OUTDIR}.tar.bz2"
108   [ -e "${OUTFILE_}" ] && { echo 'File "'${OUTFILE_}'" already exists, aborting.'>&2 ; rm -r "${OUTDIR}"; exit 1; }
109   OUTFILE=${OUTFILE_}
110   touch "${OUTFILE}"
111 fi
112
113 if [ "$(id -u)" != "0" ] ; then
114   NOTROOT=1
115   echo "W: Running without root permissions. Not all data will be collected."
116 fi
117
118 # check whether a binary is available and executable
119 exectest() {
120   if [ -z "$1" ] ; then
121     echo 'Usage: exectest <binary>'>&2
122     return 1
123   else
124     if test -e "$(which $1)" ; then
125       return 0
126     else
127       grep -q "^$1"'$' missing_tools 2>/dev/null || echo "$1" >> missing_tools
128       return 1
129     fi
130   fi
131 }
132
133 # echo a list of all disks and their size
134 # taken from http://cvs.debian.org/fai/lib/disk-info
135 diskandsize() {
136   local isdisk major minor blocks device suffix
137   while read major minor blocks device suffix; do
138     isdisk=1
139     # skip ide cdrom
140     [ -f /proc/ide/$device/media ] && grep -q cdrom /proc/ide/$device/media && isdisk=0
141     [ "$isdisk" -eq 1 ] && echo "$device $blocks"
142   done
143 }
144
145 list_disks() {
146   # print only every second entry; used by disk_info
147   i=0
148   for ent in $@; do
149     if [ "$i" -eq 0 ]; then
150       echo $ent
151       i=1
152     else
153       i=0
154     fi
155   done
156 }
157
158 disk_info() {
159   # the variable holds a space separated list of devices and their block size
160   device_size=`grep -E ' cciss/c.d.$| ida/c.d.$| rd/c.d.$| hd.$| sd.$|/disc$' /proc/partitions | diskandsize`
161   # a list of all local disks, without size
162   disklist=`list_disks $device_size`
163 }
164
165
166 cd "${OUTDIR}" || exit 1
167 (
168   [ -n "$GENERATE_FILE" ]      && echo "Output file:      $OUTFILE"
169   [ -n "$GENERATE_DIRECTORY" ] && echo "Output directory: $OUTDIR"
170   echo
171   echo "This might take a few seconds/minutes. Please be patient..."
172
173   # some sysinfo
174   date > date
175   if [ -r /etc/grml_version ] ; then
176      cat /etc/grml_version > grml_version
177   fi
178   if [ -r /etc/debian_version ] ; then
179      cat /etc/debian_version > debian_version
180   fi
181   uname -a > uname
182
183   # disks / devices
184   [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi
185   exectest lspci && lspci -nn > lspci
186   cat /proc/partitions > partitions
187   find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
188   df -h > df 2>/dev/null
189   for i in free lsmod mount lsdev lspnp lsusb ; do
190     exectest $i && $i > $i
191   done
192   swapon -s > swapon 2>swapon.error
193
194   # proc stuff
195   for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
196     mdstat meminfo modules mtrr pci version ; do
197     [ -r /proc/$i ] && cat /proc/$i > proc_$i
198   done
199   exectest sysdump  && sysdump > sysdump 2>sysdump.error
200
201   # log
202   dmesg > dmesg.cur
203
204   # hwinfo
205   exectest discover && discover -v --type-summary --enable-bus all > discover 2> discover.2
206   exectest hwinfo   && hwinfo log=hwinfo
207   exectest numactl  && numactl --hardware > numactl
208   exectest x86info  && x86info > x86info 2>x86info.2
209   exectest lscpu    && lscpu > lscpu
210
211   # net stuff, net-tools:
212   exectest ifconfig && ifconfig -v -a > ifconfig
213   exectest route    && route -n       > route
214
215   # net stuff, iproute:
216   exectest ip && ip addrlabel list > ip_addrlabel
217   exectest ip && ip addr show      > ip_addr
218   exectest ip && ip link show      > ip_link
219   exectest ip && ip maddr show     > ip_maddr
220   exectest ip && ip mroute show    > ip_mroute
221   exectest ip && ip mrule show     > ip_mrule
222   exectest ip && ip neigh show     > ip_neigh
223   exectest ip && ip netns list     > ip_netns
224   exectest ip && ip ntable show    > ip_ntable
225   exectest ip && ip route show     > ip_route
226   exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
227                    grep -v '^#' /etc/iproute2/rt_tables | while read table name ; do
228                      ip route show table "${table}" > "ip_route_table_${table}"
229                    done
230                  fi
231   exectest ip && ip rule show      > ip_rule
232   exectest ip && ip tunnel show    > ip_tunnel
233   exectest ip && ip tuntap show    > ip_tuntap
234
235   # software
236   if exectest dpkg ; then
237     dpkg --get-selections   > dpkg_get_selections
238     COLUMNS=300 dpkg --list > dpkg_list
239   fi
240
241   # power management
242   exectest laptop-detect  && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
243   if [ -r /proc/acpi/info ] ; then
244     cat /proc/acpi/info > acpi_info
245   fi
246
247   exectest acpi && acpi > acpi 2> acpi.error && acpi -v > acpi.version
248   [ -r /proc/apm/ ] && apm > apm
249
250   if exectest mcelog ; then
251     mcelog > mcelog 2>mcelog.error
252   fi
253
254   # kernel stuff
255   if [ -r /proc/config.gz ] ; then
256     zcat /proc/config.gz > kernelconfig
257   else
258     [ -r /boot/config-$UNAME ] && cat /boot/config-$UNAME > kernelconfig
259   fi
260
261   exectest dpkg && COLUMNS=1000 dpkg -l linux-image-$UNAME 2>running_kernel.error \
262            | grep linux-image-$UNAME | tr -s ' ' > running_kernel 2>>running_kernel.error
263   dpkg -S /boot/vmlinuz-$(uname -r) >> running_kernel 2>>running_kernel.error
264
265   # X stuff
266   if [ -n "${DISPLAY}" ] ; then
267     exectest xviddetect  && xviddetect         > xviddetect
268     exectest xvidtune    && xvidtune -show     > xdivtune
269     exectest xrandr      && xrandr             > xrandr
270     exectest xdpyinfo    && xdpyinfo           > xdpyinfo
271     X -version > x_version 2>&1
272   fi
273
274   for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
275     cp /var/log/$i log_$i 2>/dev/null
276   done
277
278   cp /etc/X11/xorg.conf    xorg.conf    2>/dev/null
279   cp /etc/modules          modules      2>/dev/null
280   cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
281
282   # as root:
283   if [ -n "$NOTROOT" ] ; then
284     echo "not running as root" > root
285   else
286     echo "running as root" > root
287     disk_info
288     exectest sfdisk     && sfdisk -d > sfdisk 2>sfdisk.error
289     exectest dmidecode  && dmidecode > dmidecode
290
291     exectest dconf && dconf -o dconf
292
293     if exectest mcelog ; then
294       mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
295     fi
296
297     if exectest edac-util ; then
298       edac-util > edac-util 2>edac-util.error
299       edac-util --report=full > edac-util_report 2>edac-util_report.error
300     fi
301
302     if exectest decode-dimms ; then
303       decode-dimms > decode-dimms 2>decode-dimms.error
304     elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
305       /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
306     fi
307
308     # proxmox
309     exectest qm && qm list > qm 2>qm.error
310     # libvirt
311     exectest virsh && virsh list >virsh 2>virsh.error
312     # openvz
313     exectest vzlist && vzlist >vzlist 2>vzlist.error
314     # vserver
315     exectest vserver-stat && vserver-stat >vserver-stat 2>vserver-stat.error
316
317     exectest mdadm && mdadm --detail /dev/md[0-9]* >> mdadm 2>mdadm.error
318
319     # LVM
320     exectest pvs && pvs > pvs 2>pvs.error
321     exectest vgs && vgs > vgs 2>vgs.error
322     exectest lvs && lvs > lvs 2>lvs.error
323     exectest lvdisplay && lvdisplay > lvdisplay 2>lvdisplay.error
324
325     exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
326     exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
327     exectest lsblk && lsblk > lsblk 2>lsblk.error
328
329     # iSCSI
330     if exectest iscsiadm ; then
331       iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
332       iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
333       iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
334       iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
335       iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
336       iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
337     fi
338
339     if exectest lsscsi ; then
340       lsscsi    > lsscsi 2>lsscsi.error
341       lsscsi -t > lsscsi_transport 2>lsscsi_transport.error
342     fi
343
344     for disk in $disklist; do
345       if exectest smartctl ; then
346         echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
347         smartctl -a /dev/$disk >> smartctl
348         echo -e "\n\n" >> smartctl
349       fi
350
351       if exectest hdparm ; then
352         echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
353         hdparm -iv /dev/$disk >> hdparm
354         echo -e "\n\n" >> hdparm
355       fi
356
357       if exectest fdisk ; then
358         echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
359         fdisk -lu /dev/$disk >>fdisk 2>>fdisk.error
360         echo -e "\n\n" >> fdisk
361       fi
362
363       if exectest parted ; then
364         echo -e "parted -s /dev/${disk}:\n" >> parted
365         parted -s /dev/$disk print >> parted
366         echo -e "\n\n" >> parted
367       fi
368
369       if exectest sdparm ; then
370         echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
371         sdparm --all --long /dev/$disk >> sdparm
372         echo -e "\n\n" >> sdparm
373       fi
374
375       if exectest sg_inq ; then
376         echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
377         sg_inq /dev/$disk >> sg_inq
378         echo -e "\n\n" >> sg_inq
379       fi
380
381       file -s /dev/$disk?* | grep -v ": empty" >> file_disk
382     done
383   fi
384 )
385
386 # get rid of empty files
387 for file in *.error ; do
388   test -s $file || rm $file
389 done
390
391 echo
392
393 cd "${WORKING_DIR}"
394
395 # create tarball
396 if [ -n "$GENERATE_FILE" ] ; then
397   tar acf "${OUTFILE}" "${OUTDIRNAME}"
398   [ -r "$OUTFILE" ] && echo "$OUTFILE ("$(ls -ahl "$OUTFILE" | awk '{print $5}')") has been generated."
399 fi
400
401 # remove (temporary) output directory if needed, else keep it, as it doubles
402 # as the real output directory.
403 if [ -z "$GENERATE_DIRECTORY" ] ; then
404   rm -r "${OUTDIR}"
405 else
406   [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
407 fi
408
409 exit 0
410
411 ## END OF FILE##################################################################