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 # Check if X server is running
177 # If xset is missing, we rely on the existence of the $DISPLAY variable.
179 if exectest xset ; then
180 if ! timeout 1s xset q &>/dev/null ; then
183 elif [ -z "${DISPLAY}" ] ; then
187 if [ "${NO_DISPLAY}" -eq 1 ] ; then
188 $_opt_quiet || echo "W: Running without X server. Not all data will be collected."
191 cd "${OUTDIR}" || exit 1
193 if ! $_opt_quiet ; then
194 [ -n "$GENERATE_FILE" ] && echo "Output file: $OUTFILE"
195 [ -n "$GENERATE_DIRECTORY" ] && echo "Output directory: $OUTDIR"
197 echo "This might take a few seconds/minutes. Please be patient..."
202 if [ -r /etc/grml_version ] ; then
203 cat /etc/grml_version > grml_version
205 if [ -r /etc/debian_version ] ; then
206 cat /etc/debian_version > debian_version
211 exectest inxi && inxi -F -xx > ./inxi 2>./inxi.error
212 exectest inxi && inxi -FJ --admin > ./inxi_admin 2>./inxi_admin.error
215 [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi
216 exectest lspci && lspci -nn > ./lspci
217 exectest lspci && lspci -vvnn > ./lspci_verbose
218 cat /proc/partitions > partitions
219 find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
220 df -h > ./df 2>/dev/null
221 for i in free lsmod mount lsdev lspnp ; do
222 exectest $i && $i > ./$i
225 if exectest lsusb ; then
227 lsusb -v > ./lsusb_verbose 2>./lsusb_verbose.error
230 swapon -s > ./swapon 2>./swapon.error
233 for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
234 mdstat meminfo modules mtrr pci uptime version ; do
235 [ -r /proc/$i ] && cat /proc/$i > proc_$i
238 if ! $_opt_quiet ; then
239 echo "Starting sysdump..."
240 echo " NOTE: if it seems to be hanging at this stage file a bug report with output of:"
241 echo " lsof -p \$(pgrep -f "\$\(which sysdump\)")"
243 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
244 if ! $_opt_quiet ; then
245 echo "Execution of sysdump finished."
248 exectest cpuid && cpuid > ./cpuid 2>./cpuid.error
250 exectest uptime && uptime > ./uptime 2>./uptime.error
256 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
257 exectest hwinfo && hwinfo log=hwinfo
258 exectest numactl && numactl --hardware > ./numactl
259 exectest x86info && x86info > ./x86info 2>./x86info.error
260 exectest lscpu && lscpu > ./lscpu
261 exectest lscpu && lscpu -e > ./lscpu_extended
264 exectest efibootmgr && efibootmgr -v >efibootmgr 2>efibootmgr.error
266 # net stuff, net-tools:
267 exectest ifconfig && ifconfig -v -a > ./ifconfig
268 exectest route && route -n > ./route
271 if exectest ethtool ; then
273 for dev in "${niclist[@]}" ; do
274 ethtool "${dev}" > ethtool_"${dev}"
277 # skip the loopback device, `ethtool --driver lo` fails with:
278 # "Cannot get driver information: Operation not supported"
281 ethtool --driver "${dev}" > ethtool_"${dev}_driver"
287 # net stuff, iproute:
288 exectest ip && ip addrlabel list > ip_addrlabel
289 exectest ip && ip addr show > ip_addr
290 exectest ip && ip link show > ip_link
291 exectest ip && ip maddr show > ip_maddr
292 exectest ip && ip mroute show > ip_mroute
293 exectest ip && ip mrule show > ip_mrule 2>ip_mrule.error
294 exectest ip && ip neigh show > ip_neigh
295 exectest ip && ip netconf > ip_netconf
296 exectest ip && ip netns list > ip_netns
297 exectest ip && ip ntable show > ip_ntable
298 exectest ip && ip route show > ip_route
299 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
300 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
301 ip route show table "${table}" > "ip_route_table_${table}" 2> "ip_route_table_${table}".error
304 exectest ip && ip rule show > ip_rule
305 exectest ip && ip tunnel show > ip_tunnel
306 exectest ip && ip tuntap show > ip_tuntap
309 if exectest dpkg ; then
310 dpkg --get-selections > dpkg_get_selections
311 COLUMNS=300 dpkg --list > dpkg_list
315 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
316 if [ -r /proc/acpi/info ] ; then
317 cat /proc/acpi/info > acpi_info
320 if exectest acpi ; then
321 acpi > ./acpi 2>acpi.error
322 acpi --everything > ./acpi.everything 2>./acpi.everything.error
323 acpi -v > ./acpi.version
325 [ -r /proc/apm/ ] && apm > ./apm
327 if exectest mcelog ; then
328 mcelog > ./mcelog 2>./mcelog.error
332 if [ -r /proc/config.gz ] ; then
333 zcat /proc/config.gz > kernelconfig
335 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
338 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
339 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
340 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
343 if [ "${NO_DISPLAY}" -eq 0 ] ; then
344 exectest xviddetect && xviddetect > ./xviddetect
345 exectest xvidtune && xvidtune -show > ./xdivtune
346 exectest xrandr && xrandr > ./xrandr
347 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
348 X -version > x_version 2>&1
351 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
352 cp /var/log/$i log_$i 2>/dev/null
355 if [ -r "$HOME"/.local/share/xorg/Xorg.0.log ] ; then
356 cp "$HOME"/.local/share/xorg/Xorg.0.log user_Xorg.0.log
359 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
360 cp /etc/modules modules 2>/dev/null
361 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
364 if [ -n "$NOTROOT" ] ; then
365 echo "not running as root" > root
367 echo "running as root" > root
370 exectest dmidecode && dmidecode > ./dmidecode
372 if exectest mcelog ; then
373 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
376 if exectest edac-util ; then
377 edac-util > ./edac-util 2>./edac-util.error
378 edac-util --report=full > edac-util_report 2>edac-util_report.error
381 if exectest decode-dimms ; then
382 decode-dimms > ./decode-dimms 2>./decode-dimms.error
383 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
384 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
387 if exectest acpidump ; then
388 acpidump > ./acpidump 2>./acpidump.error
391 if exectest mokutil ; then
392 mokutil --sb-state > ./mokutil_state 2>./mokutil_state.error
396 exectest qm && qm list > ./qm 2>./qm.error
398 exectest virsh && virsh list >./virsh 2>./virsh.error
400 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
402 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
404 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
407 exectest pvs && pvs > ./pvs 2>./pvs.error
408 exectest vgs && vgs > ./vgs 2>./vgs.error
409 exectest lvs && lvs > ./lvs 2>./lvs.error
410 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
412 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
413 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
414 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
417 if exectest iscsiadm ; then
418 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
419 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
420 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
421 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
422 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
423 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
426 if exectest lsscsi ; then
427 lsscsi > ./lsscsi 2>./lsscsi.error
428 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
431 for disk in $disklist; do
432 if exectest sfdisk && [[ -b "/dev/${disk}" ]] ; then
433 sfdisk -d "/dev/${disk}" > "./sfdisk_${disk}" 2>"./sfdisk_${disk}.error"
436 if exectest smartctl ; then
437 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
438 smartctl -a "/dev/$disk" >> ./smartctl
439 echo -e "\n\n" >> ./smartctl
442 if exectest hdparm ; then
443 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
444 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
445 echo -e "\n\n" >> hdparm
448 if exectest fdisk ; then
449 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
450 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
451 echo -e "\n\n" >> fdisk
454 if exectest parted ; then
455 echo -e "parted -s /dev/${disk}:\n" >> parted
456 parted -s "/dev/$disk" print >> ./parted
457 echo -e "\n\n" >> parted
460 if exectest sdparm ; then
461 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
462 sdparm --all --long "/dev/$disk" >> ./sdparm
463 echo -e "\n\n" >> sdparm
466 if exectest sg_inq ; then
467 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
468 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
469 echo -e "\n\n" >> sg_inq
472 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
477 # get rid of empty files
478 for file in *.error ; do
479 test -s "$file" || rm -- "$file"
487 if [ -n "$GENERATE_FILE" ] ; then
488 tar acf "${OUTFILE}" "${OUTDIRNAME}"
489 if ! $_opt_quiet ; then
490 # shellcheck disable=SC2012
491 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
495 # remove (temporary) output directory if needed, else keep it, as it doubles
496 # as the real output directory.
497 if [ -z "$GENERATE_DIRECTORY" ] ; then
500 if ! $_opt_quiet ; then
501 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
507 ## END OF FILE##################################################################