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 cat /proc/partitions > partitions
198 find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
199 df -h > ./df 2>/dev/null
200 for i in free lsmod mount lsdev lspnp lsusb ; do
201 exectest $i && $i > ./$i
203 swapon -s > ./swapon 2>./swapon.error
206 for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
207 mdstat meminfo modules mtrr pci version ; do
208 [ -r /proc/$i ] && cat /proc/$i > proc_$i
210 exectest sysdump && sysdump > ./sysdump 2>./sysdump.error
216 exectest discover && discover -v --type-summary --enable-bus all > ./discover 2>./discover.error
217 exectest hwinfo && hwinfo log=hwinfo
218 exectest numactl && numactl --hardware > ./numactl
219 exectest x86info && x86info > ./x86info 2>./x86info.error
220 exectest lscpu && lscpu > ./lscpu
223 exectest efibootmgr && efibootmgr -v > efibootmgr
225 # net stuff, net-tools:
226 exectest ifconfig && ifconfig -v -a > ./ifconfig
227 exectest route && route -n > ./route
229 # net stuff, iproute:
230 exectest ip && ip addrlabel list > ip_addrlabel
231 exectest ip && ip addr show > ip_addr
232 exectest ip && ip link show > ip_link
233 exectest ip && ip maddr show > ip_maddr
234 exectest ip && ip mroute show > ip_mroute
235 exectest ip && ip mrule show > ip_mrule 2>ip_mrule.error
236 exectest ip && ip neigh show > ip_neigh
237 exectest ip && ip netns list > ip_netns
238 exectest ip && ip ntable show > ip_ntable
239 exectest ip && ip route show > ip_route
240 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
241 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
242 ip route show table "${table}" > "ip_route_table_${table}"
245 exectest ip && ip rule show > ip_rule
246 exectest ip && ip tunnel show > ip_tunnel
247 exectest ip && ip tuntap show > ip_tuntap
250 if exectest dpkg ; then
251 dpkg --get-selections > dpkg_get_selections
252 COLUMNS=300 dpkg --list > dpkg_list
256 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
257 if [ -r /proc/acpi/info ] ; then
258 cat /proc/acpi/info > acpi_info
261 if exectest acpi ; then
262 acpi > ./acpi 2>acpi.error
263 acpi --everything > ./acpi.everything 2>./acpi.everything.error
264 acpi -v > ./acpi.version
266 [ -r /proc/apm/ ] && apm > ./apm
268 if exectest mcelog ; then
269 mcelog > ./mcelog 2>./mcelog.error
273 if [ -r /proc/config.gz ] ; then
274 zcat /proc/config.gz > kernelconfig
276 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
279 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
280 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
281 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
284 if [ -n "${DISPLAY}" ] ; then
285 exectest xviddetect && xviddetect > ./xviddetect
286 exectest xvidtune && xvidtune -show > ./xdivtune
287 exectest xrandr && xrandr > ./xrandr
288 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
289 X -version > x_version 2>&1
292 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
293 cp /var/log/$i log_$i 2>/dev/null
296 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
297 cp /etc/modules modules 2>/dev/null
298 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
301 if [ -n "$NOTROOT" ] ; then
302 echo "not running as root" > root
304 echo "running as root" > root
306 exectest sfdisk && sfdisk -d > ./sfdisk 2>./sfdisk.error
307 exectest dmidecode && dmidecode > ./dmidecode
309 exectest dconf && dconf -o dconf
311 if exectest mcelog ; then
312 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
315 if exectest edac-util ; then
316 edac-util > ./edac-util 2>./edac-util.error
317 edac-util --report=full > edac-util_report 2>edac-util_report.error
320 if exectest decode-dimms ; then
321 decode-dimms > ./decode-dimms 2>./decode-dimms.error
322 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
323 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
327 exectest qm && qm list > ./qm 2>./qm.error
329 exectest virsh && virsh list >./virsh 2>./virsh.error
331 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
333 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
335 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
338 exectest pvs && pvs > ./pvs 2>./pvs.error
339 exectest vgs && vgs > ./vgs 2>./vgs.error
340 exectest lvs && lvs > ./lvs 2>./lvs.error
341 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
343 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
344 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
345 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
348 if exectest iscsiadm ; then
349 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
350 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
351 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
352 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
353 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
354 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
357 if exectest lsscsi ; then
358 lsscsi > ./lsscsi 2>./lsscsi.error
359 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
362 for disk in $disklist; do
363 if exectest smartctl ; then
364 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
365 smartctl -a "/dev/$disk" >> ./smartctl
366 echo -e "\n\n" >> ./smartctl
369 if exectest hdparm ; then
370 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
371 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
372 echo -e "\n\n" >> hdparm
375 if exectest fdisk ; then
376 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
377 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
378 echo -e "\n\n" >> fdisk
381 if exectest parted ; then
382 echo -e "parted -s /dev/${disk}:\n" >> parted
383 parted -s "/dev/$disk" print >> ./parted
384 echo -e "\n\n" >> parted
387 if exectest sdparm ; then
388 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
389 sdparm --all --long "/dev/$disk" >> ./sdparm
390 echo -e "\n\n" >> sdparm
393 if exectest sg_inq ; then
394 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
395 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
396 echo -e "\n\n" >> sg_inq
399 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
404 # get rid of empty files
405 for file in *.error ; do
406 test -s "$file" || rm -- "$file"
414 if [ -n "$GENERATE_FILE" ] ; then
415 tar acf "${OUTFILE}" "${OUTDIRNAME}"
416 if ! $_opt_quiet ; then
417 # shellcheck disable=SC2012
418 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
422 # remove (temporary) output directory if needed, else keep it, as it doubles
423 # as the real output directory.
424 if [ -z "$GENERATE_DIRECTORY" ] ; then
427 if ! $_opt_quiet ; then
428 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
434 ## END OF FILE##################################################################