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 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 version ; do
215 [ -r /proc/$i ] && cat /proc/$i > proc_$i
217 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
223 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
224 exectest hwinfo && hwinfo log=hwinfo
225 exectest numactl && numactl --hardware > ./numactl
226 exectest x86info && x86info > ./x86info 2>./x86info.error
227 exectest lscpu && lscpu > ./lscpu
230 exectest efibootmgr && efibootmgr -v > efibootmgr
232 # net stuff, net-tools:
233 exectest ifconfig && ifconfig -v -a > ./ifconfig
234 exectest route && route -n > ./route
236 # net stuff, iproute:
237 exectest ip && ip addrlabel list > ip_addrlabel
238 exectest ip && ip addr show > ip_addr
239 exectest ip && ip link show > ip_link
240 exectest ip && ip maddr show > ip_maddr
241 exectest ip && ip mroute show > ip_mroute
242 exectest ip && ip mrule show > ip_mrule 2>ip_mrule.error
243 exectest ip && ip neigh show > ip_neigh
244 exectest ip && ip netns list > ip_netns
245 exectest ip && ip ntable show > ip_ntable
246 exectest ip && ip route show > ip_route
247 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
248 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
249 ip route show table "${table}" > "ip_route_table_${table}"
252 exectest ip && ip rule show > ip_rule
253 exectest ip && ip tunnel show > ip_tunnel
254 exectest ip && ip tuntap show > ip_tuntap
257 if exectest dpkg ; then
258 dpkg --get-selections > dpkg_get_selections
259 COLUMNS=300 dpkg --list > dpkg_list
263 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
264 if [ -r /proc/acpi/info ] ; then
265 cat /proc/acpi/info > acpi_info
268 if exectest acpi ; then
269 acpi > ./acpi 2>acpi.error
270 acpi --everything > ./acpi.everything 2>./acpi.everything.error
271 acpi -v > ./acpi.version
273 [ -r /proc/apm/ ] && apm > ./apm
275 if exectest mcelog ; then
276 mcelog > ./mcelog 2>./mcelog.error
280 if [ -r /proc/config.gz ] ; then
281 zcat /proc/config.gz > kernelconfig
283 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
286 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
287 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
288 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
291 if [ -n "${DISPLAY}" ] ; then
292 exectest xviddetect && xviddetect > ./xviddetect
293 exectest xvidtune && xvidtune -show > ./xdivtune
294 exectest xrandr && xrandr > ./xrandr
295 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
296 X -version > x_version 2>&1
299 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
300 cp /var/log/$i log_$i 2>/dev/null
303 if [ -r "$HOME"/.local/share/xorg/Xorg.0.log ] ; then
304 cp "$HOME"/.local/share/xorg/Xorg.0.log user_Xorg.0.log
307 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
308 cp /etc/modules modules 2>/dev/null
309 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
312 if [ -n "$NOTROOT" ] ; then
313 echo "not running as root" > root
315 echo "running as root" > root
317 exectest sfdisk && sfdisk -d > ./sfdisk 2>./sfdisk.error
318 exectest dmidecode && dmidecode > ./dmidecode
320 exectest dconf && dconf -o dconf
322 if exectest mcelog ; then
323 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
326 if exectest edac-util ; then
327 edac-util > ./edac-util 2>./edac-util.error
328 edac-util --report=full > edac-util_report 2>edac-util_report.error
331 if exectest decode-dimms ; then
332 decode-dimms > ./decode-dimms 2>./decode-dimms.error
333 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
334 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
337 if exectest acpidump ; then
338 acpidump > ./acpidump 2>./acpidump.error
341 if exectest mokutil ; then
342 mokutil --sb-state > ./mokutil_state 2>./mokutil_state.error
346 exectest qm && qm list > ./qm 2>./qm.error
348 exectest virsh && virsh list >./virsh 2>./virsh.error
350 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
352 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
354 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
357 exectest pvs && pvs > ./pvs 2>./pvs.error
358 exectest vgs && vgs > ./vgs 2>./vgs.error
359 exectest lvs && lvs > ./lvs 2>./lvs.error
360 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
362 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
363 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
364 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
367 if exectest iscsiadm ; then
368 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
369 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
370 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
371 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
372 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
373 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
376 if exectest lsscsi ; then
377 lsscsi > ./lsscsi 2>./lsscsi.error
378 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
381 for disk in $disklist; do
382 if exectest smartctl ; then
383 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
384 smartctl -a "/dev/$disk" >> ./smartctl
385 echo -e "\n\n" >> ./smartctl
388 if exectest hdparm ; then
389 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
390 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
391 echo -e "\n\n" >> hdparm
394 if exectest fdisk ; then
395 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
396 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
397 echo -e "\n\n" >> fdisk
400 if exectest parted ; then
401 echo -e "parted -s /dev/${disk}:\n" >> parted
402 parted -s "/dev/$disk" print >> ./parted
403 echo -e "\n\n" >> parted
406 if exectest sdparm ; then
407 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
408 sdparm --all --long "/dev/$disk" >> ./sdparm
409 echo -e "\n\n" >> sdparm
412 if exectest sg_inq ; then
413 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
414 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
415 echo -e "\n\n" >> sg_inq
418 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
423 # get rid of empty files
424 for file in *.error ; do
425 test -s "$file" || rm -- "$file"
433 if [ -n "$GENERATE_FILE" ] ; then
434 tar acf "${OUTFILE}" "${OUTDIRNAME}"
435 if ! $_opt_quiet ; then
436 # shellcheck disable=SC2012
437 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
441 # remove (temporary) output directory if needed, else keep it, as it doubles
442 # as the real output directory.
443 if [ -z "$GENERATE_DIRECTORY" ] ; then
446 if ! $_opt_quiet ; then
447 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
453 ## END OF FILE##################################################################