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
326 if exectest acpidump ; then
327 acpidump > ./acpidump 2>./acpidump.error
331 exectest qm && qm list > ./qm 2>./qm.error
333 exectest virsh && virsh list >./virsh 2>./virsh.error
335 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
337 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
339 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
342 exectest pvs && pvs > ./pvs 2>./pvs.error
343 exectest vgs && vgs > ./vgs 2>./vgs.error
344 exectest lvs && lvs > ./lvs 2>./lvs.error
345 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
347 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
348 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
349 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
352 if exectest iscsiadm ; then
353 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
354 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
355 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
356 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
357 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
358 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
361 if exectest lsscsi ; then
362 lsscsi > ./lsscsi 2>./lsscsi.error
363 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
366 for disk in $disklist; do
367 if exectest smartctl ; then
368 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
369 smartctl -a "/dev/$disk" >> ./smartctl
370 echo -e "\n\n" >> ./smartctl
373 if exectest hdparm ; then
374 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
375 hdparm -iv "/dev/$disk" >> ./hdparm 2>> ./hdparm.error
376 echo -e "\n\n" >> hdparm
379 if exectest fdisk ; then
380 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
381 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
382 echo -e "\n\n" >> fdisk
385 if exectest parted ; then
386 echo -e "parted -s /dev/${disk}:\n" >> parted
387 parted -s "/dev/$disk" print >> ./parted
388 echo -e "\n\n" >> parted
391 if exectest sdparm ; then
392 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
393 sdparm --all --long "/dev/$disk" >> ./sdparm
394 echo -e "\n\n" >> sdparm
397 if exectest sg_inq ; then
398 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
399 sg_inq "/dev/$disk" >> ./sg_inq 2>> ./sg_inq.error
400 echo -e "\n\n" >> sg_inq
403 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
408 # get rid of empty files
409 for file in *.error ; do
410 test -s "$file" || rm -- "$file"
418 if [ -n "$GENERATE_FILE" ] ; then
419 tar acf "${OUTFILE}" "${OUTDIRNAME}"
420 if ! $_opt_quiet ; then
421 # shellcheck disable=SC2012
422 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
426 # remove (temporary) output directory if needed, else keep it, as it doubles
427 # as the real output directory.
428 if [ -z "$GENERATE_DIRECTORY" ] ; then
431 if ! $_opt_quiet ; then
432 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
438 ## END OF FILE##################################################################