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 exectest inxi && inxi -F -xx > ./inxi 2>./inxi.error
196 exectest inxi && inxi -FJ --admin > ./inxi_admin 2>./inxi_admin.error
199 [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi
200 exectest lspci && lspci -nn > ./lspci
201 exectest lspci && lspci -vvnn > ./lspci_verbose
202 cat /proc/partitions > partitions
203 find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
204 df -h > ./df 2>/dev/null
205 for i in free lsmod mount lsdev lspnp ; do
206 exectest $i && $i > ./$i
209 if exectest lsusb ; then
211 lsusb -v > ./lsusb_verbose 2>./lsusb_verbose.error
214 swapon -s > ./swapon 2>./swapon.error
217 for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
218 mdstat meminfo modules mtrr pci uptime version ; do
219 [ -r /proc/$i ] && cat /proc/$i > proc_$i
222 if ! $_opt_quiet ; then
223 echo "Starting sysdump..."
224 echo " NOTE: if it seems to be hanging at this stage file a bug report with output of:"
225 echo " lsof -p \$(pgrep -f "\$\(which sysdump\)")"
227 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
228 if ! $_opt_quiet ; then
229 echo "Execution of sysdump finished."
232 exectest cpuid && cpuid > ./cpuid 2>./cpuid.error
234 exectest uptime && uptime > ./uptime 2>./uptime.error
240 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
241 exectest hwinfo && hwinfo log=hwinfo
242 exectest numactl && numactl --hardware > ./numactl
243 exectest x86info && x86info > ./x86info 2>./x86info.error
244 exectest lscpu && lscpu > ./lscpu
245 exectest lscpu && lscpu -e > ./lscpu_extended
248 exectest efibootmgr && efibootmgr -v >efibootmgr 2>efibootmgr.error
250 # net stuff, net-tools:
251 exectest ifconfig && ifconfig -v -a > ./ifconfig
252 exectest route && route -n > ./route
255 if exectest ethtool ; then
257 for dev in "${niclist[@]}" ; do
258 ethtool "${dev}" > ethtool_"${dev}"
261 # skip the loopback device, `ethtool --driver lo` fails with:
262 # "Cannot get driver information: Operation not supported"
265 ethtool --driver "${dev}" > ethtool_"${dev}_driver"
271 # net stuff, iproute:
272 exectest ip && ip addrlabel list > ip_addrlabel
273 exectest ip && ip addr show > ip_addr
274 exectest ip && ip link show > ip_link
275 exectest ip && ip maddr show > ip_maddr
276 exectest ip && ip mroute show > ip_mroute
277 exectest ip && ip mrule show > ip_mrule 2>ip_mrule.error
278 exectest ip && ip neigh show > ip_neigh
279 exectest ip && ip netconf > ip_netconf
280 exectest ip && ip netns list > ip_netns
281 exectest ip && ip ntable show > ip_ntable
282 exectest ip && ip route show > ip_route
283 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
284 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
285 ip route show table "${table}" > "ip_route_table_${table}" 2> "ip_route_table_${table}".error
288 exectest ip && ip rule show > ip_rule
289 exectest ip && ip tunnel show > ip_tunnel
290 exectest ip && ip tuntap show > ip_tuntap
293 if exectest dpkg ; then
294 dpkg --get-selections > dpkg_get_selections
295 COLUMNS=300 dpkg --list > dpkg_list
299 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
300 if [ -r /proc/acpi/info ] ; then
301 cat /proc/acpi/info > acpi_info
304 if exectest acpi ; then
305 acpi > ./acpi 2>acpi.error
306 acpi --everything > ./acpi.everything 2>./acpi.everything.error
307 acpi -v > ./acpi.version
309 [ -r /proc/apm/ ] && apm > ./apm
311 if exectest mcelog ; then
312 mcelog > ./mcelog 2>./mcelog.error
316 if [ -r /proc/config.gz ] ; then
317 zcat /proc/config.gz > kernelconfig
319 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
322 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
323 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
324 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
327 if [ -n "${DISPLAY}" ] ; then
328 exectest xviddetect && xviddetect > ./xviddetect
329 exectest xvidtune && xvidtune -show > ./xdivtune
330 exectest xrandr && xrandr > ./xrandr
331 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
332 X -version > x_version 2>&1
335 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
336 cp /var/log/$i log_$i 2>/dev/null
339 if [ -r "$HOME"/.local/share/xorg/Xorg.0.log ] ; then
340 cp "$HOME"/.local/share/xorg/Xorg.0.log user_Xorg.0.log
343 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
344 cp /etc/modules modules 2>/dev/null
345 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
348 if [ -n "$NOTROOT" ] ; then
349 echo "not running as root" > root
351 echo "running as root" > root
354 exectest dmidecode && dmidecode > ./dmidecode
356 if exectest mcelog ; then
357 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
360 if exectest edac-util ; then
361 edac-util > ./edac-util 2>./edac-util.error
362 edac-util --report=full > edac-util_report 2>edac-util_report.error
365 if exectest decode-dimms ; then
366 decode-dimms > ./decode-dimms 2>./decode-dimms.error
367 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
368 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
371 if exectest acpidump ; then
372 acpidump > ./acpidump 2>./acpidump.error
375 if exectest mokutil ; then
376 mokutil --sb-state > ./mokutil_state 2>./mokutil_state.error
380 exectest qm && qm list > ./qm 2>./qm.error
382 exectest virsh && virsh list >./virsh 2>./virsh.error
384 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
386 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
388 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
391 exectest pvs && pvs > ./pvs 2>./pvs.error
392 exectest vgs && vgs > ./vgs 2>./vgs.error
393 exectest lvs && lvs > ./lvs 2>./lvs.error
394 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
396 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
397 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
398 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
401 if exectest iscsiadm ; then
402 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
403 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
404 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
405 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
406 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
407 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
410 if exectest lsscsi ; then
411 lsscsi > ./lsscsi 2>./lsscsi.error
412 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
415 for disk in $disklist; do
416 if exectest sfdisk && [[ -b "/dev/${disk}" ]] ; then
417 sfdisk -d "/dev/${disk}" > "./sfdisk_${disk}" 2>"./sfdisk_${disk}.error"
420 if exectest smartctl ; then
421 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
422 smartctl -a "/dev/$disk" >> ./smartctl
423 echo -e "\n\n" >> ./smartctl
426 if exectest hdparm ; then
427 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
428 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
429 echo -e "\n\n" >> hdparm
432 if exectest fdisk ; then
433 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
434 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
435 echo -e "\n\n" >> fdisk
438 if exectest parted ; then
439 echo -e "parted -s /dev/${disk}:\n" >> parted
440 parted -s "/dev/$disk" print >> ./parted
441 echo -e "\n\n" >> parted
444 if exectest sdparm ; then
445 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
446 sdparm --all --long "/dev/$disk" >> ./sdparm
447 echo -e "\n\n" >> sdparm
450 if exectest sg_inq ; then
451 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
452 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
453 echo -e "\n\n" >> sg_inq
456 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
461 # get rid of empty files
462 for file in *.error ; do
463 test -s "$file" || rm -- "$file"
471 if [ -n "$GENERATE_FILE" ] ; then
472 tar acf "${OUTFILE}" "${OUTDIRNAME}"
473 if ! $_opt_quiet ; then
474 # shellcheck disable=SC2012
475 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
479 # remove (temporary) output directory if needed, else keep it, as it doubles
480 # as the real output directory.
481 if [ -z "$GENERATE_DIRECTORY" ] ; then
484 if ! $_opt_quiet ; then
485 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
491 ## END OF FILE##################################################################