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 uptime version ; do
215 [ -r /proc/$i ] && cat /proc/$i > proc_$i
217 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
219 exectest uptime && uptime > ./uptime 2>./uptime.error
225 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
226 exectest hwinfo && hwinfo log=hwinfo
227 exectest numactl && numactl --hardware > ./numactl
228 exectest x86info && x86info > ./x86info 2>./x86info.error
229 exectest lscpu && lscpu > ./lscpu
232 exectest efibootmgr && efibootmgr -v > efibootmgr
234 # net stuff, net-tools:
235 exectest ifconfig && ifconfig -v -a > ./ifconfig
236 exectest route && route -n > ./route
238 # net stuff, iproute:
239 exectest ip && ip addrlabel list > ip_addrlabel
240 exectest ip && ip addr show > ip_addr
241 exectest ip && ip link show > ip_link
242 exectest ip && ip maddr show > ip_maddr
243 exectest ip && ip mroute show > ip_mroute
244 exectest ip && ip mrule show > ip_mrule 2>ip_mrule.error
245 exectest ip && ip neigh show > ip_neigh
246 exectest ip && ip netns list > ip_netns
247 exectest ip && ip ntable show > ip_ntable
248 exectest ip && ip route show > ip_route
249 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
250 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
251 ip route show table "${table}" > "ip_route_table_${table}"
254 exectest ip && ip rule show > ip_rule
255 exectest ip && ip tunnel show > ip_tunnel
256 exectest ip && ip tuntap show > ip_tuntap
259 if exectest dpkg ; then
260 dpkg --get-selections > dpkg_get_selections
261 COLUMNS=300 dpkg --list > dpkg_list
265 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
266 if [ -r /proc/acpi/info ] ; then
267 cat /proc/acpi/info > acpi_info
270 if exectest acpi ; then
271 acpi > ./acpi 2>acpi.error
272 acpi --everything > ./acpi.everything 2>./acpi.everything.error
273 acpi -v > ./acpi.version
275 [ -r /proc/apm/ ] && apm > ./apm
277 if exectest mcelog ; then
278 mcelog > ./mcelog 2>./mcelog.error
282 if [ -r /proc/config.gz ] ; then
283 zcat /proc/config.gz > kernelconfig
285 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
288 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
289 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
290 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
293 if [ -n "${DISPLAY}" ] ; then
294 exectest xviddetect && xviddetect > ./xviddetect
295 exectest xvidtune && xvidtune -show > ./xdivtune
296 exectest xrandr && xrandr > ./xrandr
297 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
298 X -version > x_version 2>&1
301 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
302 cp /var/log/$i log_$i 2>/dev/null
305 if [ -r "$HOME"/.local/share/xorg/Xorg.0.log ] ; then
306 cp "$HOME"/.local/share/xorg/Xorg.0.log user_Xorg.0.log
309 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
310 cp /etc/modules modules 2>/dev/null
311 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
314 if [ -n "$NOTROOT" ] ; then
315 echo "not running as root" > root
317 echo "running as root" > root
319 exectest sfdisk && sfdisk -d > ./sfdisk 2>./sfdisk.error
320 exectest dmidecode && dmidecode > ./dmidecode
322 exectest dconf && dconf -o dconf
324 if exectest mcelog ; then
325 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
328 if exectest edac-util ; then
329 edac-util > ./edac-util 2>./edac-util.error
330 edac-util --report=full > edac-util_report 2>edac-util_report.error
333 if exectest decode-dimms ; then
334 decode-dimms > ./decode-dimms 2>./decode-dimms.error
335 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
336 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
339 if exectest acpidump ; then
340 acpidump > ./acpidump 2>./acpidump.error
343 if exectest mokutil ; then
344 mokutil --sb-state > ./mokutil_state 2>./mokutil_state.error
348 exectest qm && qm list > ./qm 2>./qm.error
350 exectest virsh && virsh list >./virsh 2>./virsh.error
352 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
354 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
356 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
359 exectest pvs && pvs > ./pvs 2>./pvs.error
360 exectest vgs && vgs > ./vgs 2>./vgs.error
361 exectest lvs && lvs > ./lvs 2>./lvs.error
362 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
364 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
365 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
366 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
369 if exectest iscsiadm ; then
370 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
371 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
372 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
373 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
374 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
375 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
378 if exectest lsscsi ; then
379 lsscsi > ./lsscsi 2>./lsscsi.error
380 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
383 for disk in $disklist; do
384 if exectest smartctl ; then
385 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
386 smartctl -a "/dev/$disk" >> ./smartctl
387 echo -e "\n\n" >> ./smartctl
390 if exectest hdparm ; then
391 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
392 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
393 echo -e "\n\n" >> hdparm
396 if exectest fdisk ; then
397 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
398 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
399 echo -e "\n\n" >> fdisk
402 if exectest parted ; then
403 echo -e "parted -s /dev/${disk}:\n" >> parted
404 parted -s "/dev/$disk" print >> ./parted
405 echo -e "\n\n" >> parted
408 if exectest sdparm ; then
409 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
410 sdparm --all --long "/dev/$disk" >> ./sdparm
411 echo -e "\n\n" >> sdparm
414 if exectest sg_inq ; then
415 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
416 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
417 echo -e "\n\n" >> sg_inq
420 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
425 # get rid of empty files
426 for file in *.error ; do
427 test -s "$file" || rm -- "$file"
435 if [ -n "$GENERATE_FILE" ] ; then
436 tar acf "${OUTFILE}" "${OUTDIRNAME}"
437 if ! $_opt_quiet ; then
438 # shellcheck disable=SC2012
439 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
443 # remove (temporary) output directory if needed, else keep it, as it doubles
444 # as the real output directory.
445 if [ -z "$GENERATE_DIRECTORY" ] ; then
448 if ! $_opt_quiet ; then
449 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
455 ## END OF FILE##################################################################