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
159 # the variable holds a newline separated list of disk block devices, excluding loopback and CD-ROM devices
160 disklist=$(lsblk -nd -o NAME -e 7,11)
163 # return list of all network devices in array "${niclist[@]}"
164 get_network_devices() {
167 for interface in /sys/class/net/* ; do
168 [ -e "${interface}" ] || continue
169 interface=$(basename "${interface}")
170 # [ "${interface}" = "lo" ] && continue
171 niclist+=("${interface}")
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 exectest lspci && lspci -vvnn > ./lspci_verbose
198 cat /proc/partitions > partitions
199 find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
200 df -h > ./df 2>/dev/null
201 for i in free lsmod mount lsdev lspnp ; do
202 exectest $i && $i > ./$i
205 if exectest lsusb ; then
207 lsusb -v > ./lsusb_verbose 2>./lsusb_verbose.error
210 swapon -s > ./swapon 2>./swapon.error
213 for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
214 mdstat meminfo modules mtrr pci uptime version ; do
215 [ -r /proc/$i ] && cat /proc/$i > proc_$i
218 if ! $_opt_quiet ; then
219 echo "Starting sysdump..."
220 echo " NOTE: if it seems to be hanging at this stage file a bug report with output of:"
221 echo " lsof -p \$(pgrep -f "\$\(which sysdump\)")"
223 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
224 if ! $_opt_quiet ; then
225 echo "Execution of sysdump finished."
228 exectest cpuid && cpuid > ./cpuid 2>./cpuid.error
230 exectest uptime && uptime > ./uptime 2>./uptime.error
236 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
237 exectest hwinfo && hwinfo log=hwinfo
238 exectest numactl && numactl --hardware > ./numactl
239 exectest x86info && x86info > ./x86info 2>./x86info.error
240 exectest lscpu && lscpu > ./lscpu
241 exectest lscpu && lscpu -e > ./lscpu_extended
244 exectest efibootmgr && efibootmgr -v >efibootmgr 2>efibootmgr.error
246 # net stuff, net-tools:
247 exectest ifconfig && ifconfig -v -a > ./ifconfig
248 exectest route && route -n > ./route
251 if exectest ethtool ; then
253 for dev in "${niclist[@]}" ; do
254 ethtool "${dev}" > ethtool_"${dev}"
257 # skip the loopback device, `ethtool --driver lo` fails with:
258 # "Cannot get driver information: Operation not supported"
261 ethtool --driver "${dev}" > ethtool_"${dev}_driver"
267 # net stuff, iproute:
268 exectest ip && ip addrlabel list > ip_addrlabel
269 exectest ip && ip addr show > ip_addr
270 exectest ip && ip link show > ip_link
271 exectest ip && ip maddr show > ip_maddr
272 exectest ip && ip mroute show > ip_mroute
273 exectest ip && ip mrule show > ip_mrule 2>ip_mrule.error
274 exectest ip && ip neigh show > ip_neigh
275 exectest ip && ip netconf > ip_netconf
276 exectest ip && ip netns list > ip_netns
277 exectest ip && ip ntable show > ip_ntable
278 exectest ip && ip route show > ip_route
279 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
280 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
281 ip route show table "${table}" > "ip_route_table_${table}" 2> "ip_route_table_${table}".error
284 exectest ip && ip rule show > ip_rule
285 exectest ip && ip tunnel show > ip_tunnel
286 exectest ip && ip tuntap show > ip_tuntap
289 if exectest dpkg ; then
290 dpkg --get-selections > dpkg_get_selections
291 COLUMNS=300 dpkg --list > dpkg_list
295 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
296 if [ -r /proc/acpi/info ] ; then
297 cat /proc/acpi/info > acpi_info
300 if exectest acpi ; then
301 acpi > ./acpi 2>acpi.error
302 acpi --everything > ./acpi.everything 2>./acpi.everything.error
303 acpi -v > ./acpi.version
305 [ -r /proc/apm/ ] && apm > ./apm
307 if exectest mcelog ; then
308 mcelog > ./mcelog 2>./mcelog.error
312 if [ -r /proc/config.gz ] ; then
313 zcat /proc/config.gz > kernelconfig
315 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
318 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
319 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
320 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
323 if [ -n "${DISPLAY}" ] ; then
324 exectest xviddetect && xviddetect > ./xviddetect
325 exectest xvidtune && xvidtune -show > ./xdivtune
326 exectest xrandr && xrandr > ./xrandr
327 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
328 X -version > x_version 2>&1
331 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
332 cp /var/log/$i log_$i 2>/dev/null
335 if [ -r "$HOME"/.local/share/xorg/Xorg.0.log ] ; then
336 cp "$HOME"/.local/share/xorg/Xorg.0.log user_Xorg.0.log
339 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
340 cp /etc/modules modules 2>/dev/null
341 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
344 if [ -n "$NOTROOT" ] ; then
345 echo "not running as root" > root
347 echo "running as root" > root
350 exectest dmidecode && dmidecode > ./dmidecode
352 if exectest mcelog ; then
353 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
356 if exectest edac-util ; then
357 edac-util > ./edac-util 2>./edac-util.error
358 edac-util --report=full > edac-util_report 2>edac-util_report.error
361 if exectest decode-dimms ; then
362 decode-dimms > ./decode-dimms 2>./decode-dimms.error
363 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
364 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
367 if exectest acpidump ; then
368 acpidump > ./acpidump 2>./acpidump.error
371 if exectest mokutil ; then
372 mokutil --sb-state > ./mokutil_state 2>./mokutil_state.error
376 exectest qm && qm list > ./qm 2>./qm.error
378 exectest virsh && virsh list >./virsh 2>./virsh.error
380 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
382 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
384 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
387 exectest pvs && pvs > ./pvs 2>./pvs.error
388 exectest vgs && vgs > ./vgs 2>./vgs.error
389 exectest lvs && lvs > ./lvs 2>./lvs.error
390 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
392 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
393 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
394 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
397 if exectest iscsiadm ; then
398 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
399 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
400 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
401 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
402 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
403 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
406 if exectest lsscsi ; then
407 lsscsi > ./lsscsi 2>./lsscsi.error
408 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
411 for disk in $disklist; do
412 if exectest sfdisk && [[ -b "/dev/${disk}" ]] ; then
413 sfdisk -d "/dev/${disk}" > "./sfdisk_${disk}" 2>"./sfdisk_${disk}.error"
416 if exectest smartctl ; then
417 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
418 smartctl -a "/dev/$disk" >> ./smartctl
419 echo -e "\n\n" >> ./smartctl
422 if exectest hdparm ; then
423 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
424 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
425 echo -e "\n\n" >> hdparm
428 if exectest fdisk ; then
429 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
430 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
431 echo -e "\n\n" >> fdisk
434 if exectest parted ; then
435 echo -e "parted -s /dev/${disk}:\n" >> parted
436 parted -s "/dev/$disk" print >> ./parted
437 echo -e "\n\n" >> parted
440 if exectest sdparm ; then
441 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
442 sdparm --all --long "/dev/$disk" >> ./sdparm
443 echo -e "\n\n" >> sdparm
446 if exectest sg_inq ; then
447 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
448 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
449 echo -e "\n\n" >> sg_inq
452 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
457 # get rid of empty files
458 for file in *.error ; do
459 test -s "$file" || rm -- "$file"
467 if [ -n "$GENERATE_FILE" ] ; then
468 tar acf "${OUTFILE}" "${OUTDIRNAME}"
469 if ! $_opt_quiet ; then
470 # shellcheck disable=SC2012
471 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
475 # remove (temporary) output directory if needed, else keep it, as it doubles
476 # as the real output directory.
477 if [ -z "$GENERATE_DIRECTORY" ] ; then
480 if ! $_opt_quiet ; then
481 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
487 ## END OF FILE##################################################################