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 ################################################################################
16 [ -n "$WORKING_DIR" -a -d "$WORKING_DIR" ] || WORKING_DIR=$(pwd)
17 VERSION='***UNRELEASED***'
19 # data collection should not be affected by user locale
23 TIMESTAMP='+%F--%H-%M-%S-%Z'
24 DATE="$(date $TIMESTAMP)"
29 _opt_output_directory=false
30 _opt_output_file=false
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.
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 -q, --quiet Don't display informational text (useful for cron usage)
49 --force Don't abort but overwrite possibly existing output file
50 --output-directory <dir> Store output files in specified directory
51 --output-file <file> Store output in specified filename (tar.XX format)
55 CMDLINE_OPTS=output-directory:,output-file:,both,directory,file,help,quiet,force
56 _opt_temp=$(getopt --name grml-hwinfo -o +bdfhq --long $CMDLINE_OPTS -- "$@")
58 echo "Try 'grml-hwinfo --help' for more information." >&2
61 eval set -- "$_opt_temp"
69 shift; OUTDIRNAME="$1"
70 GENERATE_DIRECTORY='1'
71 _opt_output_directory=true
72 $_opt_output_file && GENERATE_FILE='1' || GENERATE_FILE=''
78 $_opt_output_directory && GENERATE_DIRECTORY='1' || GENERATE_DIRECTORY=''
81 GENERATE_DIRECTORY='1'
89 GENERATE_DIRECTORY='1'
102 echo "Internal getopt error!" >&2
109 if ! $_opt_quiet ; then
110 echo "$PN ${VERSION} - collect hardware information"
113 # Generate output/temporary directory name & path, and output file path
114 [ -n "$OUTDIRNAME" ] || OUTDIRNAME="grml-hwinfo-${DATE}"
115 if $_opt_output_directory ; then
116 OUTDIR="${OUTDIRNAME}"
118 OUTDIR="${WORKING_DIR}/${OUTDIRNAME}"
121 if $_opt_force ; then
124 mkdir "${OUTDIR}" || { echo "Directory '${OUTDIR}' already exists, aborting." >&2 ; exit 1; }
127 if [ -n "$GENERATE_FILE" ] ; then
128 [ -n "$OUTFILE" ] && OUTFILE_="$OUTFILE" || OUTFILE_="${OUTDIR}.tar.bz2"
129 if ! $_opt_force ; then
130 [ -e "${OUTFILE_}" ] && { echo "File '${OUTFILE_}' already exists, aborting." >&2 ; rm -r "${OUTDIR}"; exit 1; }
136 if [ "$(id -u)" != "0" ] ; then
138 $_opt_quiet || echo "W: Running without root permissions. Not all data will be collected."
141 # check whether a binary is available and executable
143 if [ -z "$1" ] ; then
144 echo 'Usage: exectest <binary>'>&2
147 if test -e "$(which "$1")" ; then
150 if ! grep -q "^$1"'$' missing_tools 2>/dev/null ; then
151 $_opt_quiet || echo "$1" >> missing_tools
158 # based on https://github.com/faiproject/fai/blob/master/lib/fai-disk-info
161 while read _ _ _ device _ ; do
164 [ "$(stat -c %G /dev/"${device}")" = "disk" ] || isdisk=0
165 [ "$isdisk" -eq 1 ] && echo "$device"
170 # the variable holds a newline separated list of devices
171 disklist=$(egrep ' etherd/e[[:digit:]]+\.[[:digit:]]+\b| i2o/hd.+\b| cciss/c.+d.+\b| ida/c.+d.+\b| rd/c.+d.+\b| fio.\b| hd.\b| sd[a-z]{1,2}\b|/disc\b| vd.\b| xvd.\b' /proc/partitions | checkdisk)
175 cd "${OUTDIR}" || exit 1
177 if ! $_opt_quiet ; then
178 [ -n "$GENERATE_FILE" ] && echo "Output file: $OUTFILE"
179 [ -n "$GENERATE_DIRECTORY" ] && echo "Output directory: $OUTDIR"
181 echo "This might take a few seconds/minutes. Please be patient..."
186 if [ -r /etc/grml_version ] ; then
187 cat /etc/grml_version > grml_version
189 if [ -r /etc/debian_version ] ; then
190 cat /etc/debian_version > debian_version
195 [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi
196 exectest lspci && lspci -nn > ./lspci
197 cat /proc/partitions > partitions
198 find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
199 df -h > ./df 2>/dev/null
200 for i in free lsmod mount lsdev lspnp lsusb ; do
201 exectest $i && $i > ./$i
203 swapon -s > ./swapon 2>./swapon.error
206 for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
207 mdstat meminfo modules mtrr pci version ; do
208 [ -r /proc/$i ] && cat /proc/$i > proc_$i
210 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
216 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
217 exectest hwinfo && hwinfo log=hwinfo
218 exectest numactl && numactl --hardware > ./numactl
219 exectest x86info && x86info > ./x86info 2>./x86info.error
220 exectest lscpu && lscpu > ./lscpu
222 # net stuff, net-tools:
223 exectest ifconfig && ifconfig -v -a > ./ifconfig
224 exectest route && route -n > ./route
226 # net stuff, iproute:
227 exectest ip && ip addrlabel list > ip_addrlabel
228 exectest ip && ip addr show > ip_addr
229 exectest ip && ip link show > ip_link
230 exectest ip && ip maddr show > ip_maddr
231 exectest ip && ip mroute show > ip_mroute
232 exectest ip && ip mrule show > ip_mrule
233 exectest ip && ip neigh show > ip_neigh
234 exectest ip && ip netns list > ip_netns
235 exectest ip && ip ntable show > ip_ntable
236 exectest ip && ip route show > ip_route
237 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
238 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
239 ip route show table "${table}" > "ip_route_table_${table}"
242 exectest ip && ip rule show > ip_rule
243 exectest ip && ip tunnel show > ip_tunnel
244 exectest ip && ip tuntap show > ip_tuntap
247 if exectest dpkg ; then
248 dpkg --get-selections > dpkg_get_selections
249 COLUMNS=300 dpkg --list > dpkg_list
253 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
254 if [ -r /proc/acpi/info ] ; then
255 cat /proc/acpi/info > acpi_info
258 if exectest acpi ; then
259 acpi > ./acpi 2>acpi.error
260 acpi --everything > ./acpi.everything 2>./acpi.everything.error
261 acpi -v > ./acpi.version
263 [ -r /proc/apm/ ] && apm > ./apm
265 if exectest mcelog ; then
266 mcelog > ./mcelog 2>./mcelog.error
270 if [ -r /proc/config.gz ] ; then
271 zcat /proc/config.gz > kernelconfig
273 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
276 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
277 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
278 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
281 if [ -n "${DISPLAY}" ] ; then
282 exectest xviddetect && xviddetect > ./xviddetect
283 exectest xvidtune && xvidtune -show > ./xdivtune
284 exectest xrandr && xrandr > ./xrandr
285 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
286 X -version > x_version 2>&1
289 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
290 cp /var/log/$i log_$i 2>/dev/null
293 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
294 cp /etc/modules modules 2>/dev/null
295 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
298 if [ -n "$NOTROOT" ] ; then
299 echo "not running as root" > root
301 echo "running as root" > root
303 exectest sfdisk && sfdisk -d > ./sfdisk 2>./sfdisk.error
304 exectest dmidecode && dmidecode > ./dmidecode
306 exectest dconf && dconf -o dconf
308 if exectest mcelog ; then
309 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
312 if exectest edac-util ; then
313 edac-util > ./edac-util 2>./edac-util.error
314 edac-util --report=full > edac-util_report 2>edac-util_report.error
317 if exectest decode-dimms ; then
318 decode-dimms > ./decode-dimms 2>./decode-dimms.error
319 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
320 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
324 exectest qm && qm list > ./qm 2>./qm.error
326 exectest virsh && virsh list >./virsh 2>./virsh.error
328 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
330 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
332 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
335 exectest pvs && pvs > ./pvs 2>./pvs.error
336 exectest vgs && vgs > ./vgs 2>./vgs.error
337 exectest lvs && lvs > ./lvs 2>./lvs.error
338 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
340 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
341 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
342 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
345 if exectest iscsiadm ; then
346 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
347 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
348 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
349 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
350 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
351 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
354 if exectest lsscsi ; then
355 lsscsi > ./lsscsi 2>./lsscsi.error
356 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
359 for disk in $disklist; do
360 if exectest smartctl ; then
361 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
362 smartctl -a "/dev/$disk" >> ./smartctl
363 echo -e "\n\n" >> ./smartctl
366 if exectest hdparm ; then
367 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
368 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
369 echo -e "\n\n" >> hdparm
372 if exectest fdisk ; then
373 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
374 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
375 echo -e "\n\n" >> fdisk
378 if exectest parted ; then
379 echo -e "parted -s /dev/${disk}:\n" >> parted
380 parted -s "/dev/$disk" print >> ./parted
381 echo -e "\n\n" >> parted
384 if exectest sdparm ; then
385 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
386 sdparm --all --long "/dev/$disk" >> ./sdparm
387 echo -e "\n\n" >> sdparm
390 if exectest sg_inq ; then
391 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
392 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
393 echo -e "\n\n" >> sg_inq
396 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
401 # get rid of empty files
402 for file in *.error ; do
403 test -s "$file" || rm -- "$file"
411 if [ -n "$GENERATE_FILE" ] ; then
412 tar acf "${OUTFILE}" "${OUTDIRNAME}"
413 if ! $_opt_quiet ; then
414 # shellcheck disable=SC2012
415 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
419 # remove (temporary) output directory if needed, else keep it, as it doubles
420 # as the real output directory.
421 if [ -z "$GENERATE_DIRECTORY" ] ; then
424 if ! $_opt_quiet ; then
425 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
431 ## END OF FILE##################################################################