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
222 # net stuff, net-tools:
223 exectest ifconfig && ifconfig -v -a > ./ifconfig
224 exectest route && route -n > ./route
226 # net stuff, iproute:
227 exectest ip && ip addrlabel list > ip_addrlabel
228 exectest ip && ip addr show > ip_addr
229 exectest ip && ip link show > ip_link
230 exectest ip && ip maddr show > ip_maddr
231 exectest ip && ip mroute show > ip_mroute
232 exectest ip && ip mrule show > ip_mrule
233 exectest ip && ip neigh show > ip_neigh
234 exectest ip && ip netns list > ip_netns
235 exectest ip && ip ntable show > ip_ntable
236 exectest ip && ip route show > ip_route
237 exectest ip && if [ -r /etc/iproute2/rt_tables ] ; then
238 grep -v '^#' /etc/iproute2/rt_tables | while read table _ ; do
239 ip route show table "${table}" > "ip_route_table_${table}"
242 exectest ip && ip rule show > ip_rule
243 exectest ip && ip tunnel show > ip_tunnel
244 exectest ip && ip tuntap show > ip_tuntap
247 if exectest dpkg ; then
248 dpkg --get-selections > dpkg_get_selections
249 COLUMNS=300 dpkg --list > dpkg_list
253 exectest laptop-detect && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
254 if [ -r /proc/acpi/info ] ; then
255 cat /proc/acpi/info > acpi_info
258 exectest acpi && acpi > ./acpi 2>acpi.error && acpi -v > ./acpi.version
259 [ -r /proc/apm/ ] && apm > ./apm
261 if exectest mcelog ; then
262 mcelog > ./mcelog 2>./mcelog.error
266 if [ -r /proc/config.gz ] ; then
267 zcat /proc/config.gz > kernelconfig
269 [ -r "/boot/config-${UNAME}" ] && cat "/boot/config-${UNAME}" > kernelconfig
272 exectest dpkg && COLUMNS=1000 dpkg -l "linux-image-${UNAME}" 2>running_kernel.error \
273 | grep "linux-image-${UNAME}" | tr -s ' ' > running_kernel 2>>running_kernel.error
274 dpkg -S "/boot/vmlinuz-$(uname -r)" >> running_kernel 2>>running_kernel.error
277 if [ -n "${DISPLAY}" ] ; then
278 exectest xviddetect && xviddetect > ./xviddetect
279 exectest xvidtune && xvidtune -show > ./xdivtune
280 exectest xrandr && xrandr > ./xrandr
281 exectest xdpyinfo && xdpyinfo > ./xdpyinfo
282 X -version > x_version 2>&1
285 for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
286 cp /var/log/$i log_$i 2>/dev/null
289 cp /etc/X11/xorg.conf xorg.conf 2>/dev/null
290 cp /etc/modules modules 2>/dev/null
291 cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null
294 if [ -n "$NOTROOT" ] ; then
295 echo "not running as root" > root
297 echo "running as root" > root
299 exectest sfdisk && sfdisk -d > ./sfdisk 2>./sfdisk.error
300 exectest dmidecode && dmidecode > ./dmidecode
302 exectest dconf && dconf -o dconf
304 if exectest mcelog ; then
305 mcelog --dmi > mcelog_dmi 2>mcelog_dmi.error
308 if exectest edac-util ; then
309 edac-util > ./edac-util 2>./edac-util.error
310 edac-util --report=full > edac-util_report 2>edac-util_report.error
313 if exectest decode-dimms ; then
314 decode-dimms > ./decode-dimms 2>./decode-dimms.error
315 elif [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
316 /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
320 exectest qm && qm list > ./qm 2>./qm.error
322 exectest virsh && virsh list >./virsh 2>./virsh.error
324 exectest vzlist && vzlist >./vzlist 2>./vzlist.error
326 exectest vserver-stat && vserver-stat >./vserver-stat 2>./vserver-stat.error
328 exectest mdadm && mdadm --detail /dev/md[0-9]* >> ./mdadm 2>./mdadm.error
331 exectest pvs && pvs > ./pvs 2>./pvs.error
332 exectest vgs && vgs > ./vgs 2>./vgs.error
333 exectest lvs && lvs > ./lvs 2>./lvs.error
334 exectest lvdisplay && lvdisplay > ./lvdisplay 2>./lvdisplay.error
336 exectest dmsetup && dmsetup ls > dmsetup_ls 2>dmsetup_ls.error
337 exectest dmsetup && dmsetup ls --tree > dmsetup_ls_tree 2>dmsetup_ls_tree.error
338 exectest lsblk && lsblk > ./lsblk 2>./lsblk.error
341 if exectest iscsiadm ; then
342 iscsiadm -m session > iscsiadm_session 2>iscsiadm_session.error
343 iscsiadm -m fw > iscsiadm_fw 2>iscsiadm_fw.error
344 iscsiadm -m host > iscsiadm_host 2>iscsiadm_host.error
345 iscsiadm -m iface > iscsiadm_iface 2>iscsiadm_iface.error
346 iscsiadm -m node > iscsiadm_node 2>iscsiadm_node.error
347 iscsiadm -m discovery > iscsiadm_discovery 2>iscsiadm_discovery.error
350 if exectest lsscsi ; then
351 lsscsi > ./lsscsi 2>./lsscsi.error
352 lsscsi -t > ./lsscsi_transport 2>./lsscsi_transport.error
355 for disk in $disklist; do
356 if exectest smartctl ; then
357 echo -e "smartctl -a /dev/${disk}:\n" >> smartctl
358 smartctl -a "/dev/$disk" >> ./smartctl
359 echo -e "\n\n" >> ./smartctl
362 if exectest hdparm ; then
363 echo -e "hdparm -iv /dev/${disk}:\n" >> hdparm
364 hdparm -iv "/dev/$disk" >> ./hdparm
365 echo -e "\n\n" >> hdparm
368 if exectest fdisk ; then
369 echo -e "fdisk -lu /dev/${disk}:\n" >> fdisk
370 fdisk -lu "/dev/$disk" >> ./fdisk 2>> ./fdisk.error
371 echo -e "\n\n" >> fdisk
374 if exectest parted ; then
375 echo -e "parted -s /dev/${disk}:\n" >> parted
376 parted -s "/dev/$disk" print >> ./parted
377 echo -e "\n\n" >> parted
380 if exectest sdparm ; then
381 echo -e "sdparm --all --long /dev/${disk}:\n" >> sdparm
382 sdparm --all --long "/dev/$disk" >> ./sdparm
383 echo -e "\n\n" >> sdparm
386 if exectest sg_inq ; then
387 echo -e "sg_inq /dev/${disk}:\n" >> sg_inq
388 sg_inq "/dev/$disk" >> ./sg_inq
389 echo -e "\n\n" >> sg_inq
392 file -s "/dev/${disk}"?* | grep -v ": empty" >> file_disk
397 # get rid of empty files
398 for file in *.error ; do
399 test -s "$file" || rm -- "$file"
407 if [ -n "$GENERATE_FILE" ] ; then
408 tar acf "${OUTFILE}" "${OUTDIRNAME}"
409 if ! $_opt_quiet ; then
410 # shellcheck disable=SC2012
411 [ -r "$OUTFILE" ] && echo "$OUTFILE ($(ls -ahl -- "$OUTFILE" | awk '{print $5}')) has been generated."
415 # remove (temporary) output directory if needed, else keep it, as it doubles
416 # as the real output directory.
417 if [ -z "$GENERATE_DIRECTORY" ] ; then
420 if ! $_opt_quiet ; then
421 [ -r "${OUTDIR}" ] && echo "${OUTDIR} has been generated."
427 ## END OF FILE##################################################################