#!/bin/ksh # # $Id: prtdiag,v 1.11 2007/01/08 01:28:07 elkner Exp $ # # Author: jens elkner # # NOTE: # ksh means "AT&T ksh93" aka "the real thing" and NOT pdksh or similar crap! unset POSIXLY_CORRECT export LC_ALL=C function PrintVersion { print "prtdiag 2.0.3 Copyright 2006 Jens Elkner. Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. " } LoadCustomizations() { [ -r /etc/prtdiag.conf ] && . /etc/prtdiag.conf [ -r ~/.prtdiag.conf ] && . ~/.prtdiag.conf } CheckEnvironment() { PATH="${PATH}:/usr/sbin:/usr/local/sbin:/sbin" P=`pkgparam LNFdmidecode BASEDIR 2>/dev/null` if [ -z "$P" ] ; then DMIDECODE=`which dmidecode 2>/dev/null` BIOSDECODE=`which biosdecode 2>/dev/null` else DMIDECODE="$P/sbin/dmidecode" BIOSDECODE="$P/sbin/biosdecode" fi P=`pkgparam LNFstatic-pciutils BASEDIR 2>/dev/null` [ -n "$P" ] || P=`pkgparam LNFpciutils BASEDIR 2>/dev/null` if [ -n "$P" ]; then LSPCI="$P/sbin/lspci" else LSPCI=`which lspci 2>/dev/null` fi EXIT="" P=`pkgparam LNFsed BASEDIR 2>/dev/null` if [ -z "$P" ] ; then SED=`which sed 2>/dev/null` [ -n "$SED" ] || EXIT="$EXIT sed" else SED="$P/bin/sed" fi P=`pkgparam LNFawk BASEDIR 2>/dev/null` if [ -z "$P" ] ; then AWK=`which awk 2>/dev/null` [ -n "$AWK" ] || EXIT="$EXIT awk" else AWK="$P/bin/awk" fi P=`pkgparam LNFgrep BASEDIR 2>/dev/null` if [ -z "$P" ] ; then GREP=`which grep 2>/dev/null` EGREP=`which egrep 2>/dev/null` [ -n "$GREP" ] || EXIT="$EXIT grep" [ -n "$EGREP" ] || EXIT="$EXIT egrep" else GREP="$P/bin/grep" EGREP="$P/bin/egrep" fi if [ -n "$EXIT" ]; then print -u2 "ERROR: Unable to find the programs $EXIT\n * Aborting *" exit 1 fi # Make sure /proc and /sys is mounted. if [ ! -f /proc/cpuinfo ]; then print -u2 " ERROR: It seems, that procfs isn't mounted on /proc. Do a '/sbin/mount -t proc -n procfs /proc' as root and try again. * Aborting *" exit 0 fi if [ ! -d /sys/devices/system/cpu ]; then print -u2 " WARNING: It seems, that sysfs isn't mounted on /sys Do a 'mount -t sysfs -n sysfs /sys' as root and try again. * System information (especially wrt. SCSI and environment) will be limited *" fi # If we're a sparc, make sure /proc/openprom is mounted. if [ "$ARCHTYPE" = "sparc" -o "$ARCHTYPE" = "sparc64" ]; then if [ ! -f /proc/openprom/name ]; then print -u2 " ERROR: Can't find /proc/openprom/name! This means that /proc/openprom isn't mounted. Mount /proc/openprom and try again. * Aborting *" exit 0 fi fi if [ "$ARCHTYPE" = "sparc" -o "$ARCHTYPE" = "sparc64" \ -o "$ARCHTYPE" = "alpha" -o "$ARCHTYPE" = "s390" ] then DMIDECODE="" BIOSDECODE="" else if [ -z "$DMIDECODE" -o ! -x $DMIDECODE ]; then DMIDECODE="" print -u2 " WARNING: A usable 'dmidecode' (package LNFdmidecode) was NOT found. * System information will be limited *" fi if [ -z "$BIOSDECODE" -o ! -x $BIOSDECODE ]; then BIOSDECODE="" print -u2 " WARNING: A usable 'biosdecode' (package LNFdmidecode) was NOT found. * System information will be limited *" fi if [ -n "$DMIDECODE" -o -n "$BIOSDECODE" ] && [ $(whoami) != "root" ]; then DMIDECODE="" BIOSDECODE="" print -u2 " WARNING: prtdiag should be run as root. * System information will be limited *" fi fi if [ -n "$LSPCI" -a -x "${LSPCI}" ]; then : else print -u2 " WARNING: A usable 'lspci' (package LNFstatic-pciutils) was NOT found. * System information will be limited *" LSPCI="" fi if [ "${SH_TYPES/e}" != ${SH_TYPES} -a ! -d /sys/class/hwmon ]; then print -u2 " WARNING: NO hardware monitor found This means, that the system hasn't loaded any sensors module up to now. You may use 'sensors-detect' (package LNFlm-sensors) to find out the modules supported by your system. modprobe them manually or add their name to your /etc/default/modules file, so that they get loaded at the system startup automatically. * System information will be limited *" fi } PrintReportHead() { SYSTEMHOSTNAME=$(uname -n) TIMEOFREPORT=$(date) OS=$(uname -r -v) HEADFMT="%-17s: %s\n" printf "\n$HEADFMT" "System Hostname" "$SYSTEMHOSTNAME" printf "$HEADFMT" "Time of Report" "$TIMEOFREPORT" printf "$HEADFMT" "Operating System" "$OS" } PrintGeneralInfos() { print " ============================= General Information ============================" HEADFMT="%-23s: %s\n" if [ "$ARCHTYPE" = "sparc" -o "$ARCHTYPE" = "sparc64" ]; then SVENDOR="Sun Microsystems" SMODEL=`cut -d "'" -f 2 /proc/openprom/banner-name` elif [ "$ARCHTYPE" = "alpha" ]; then SVENDOR="IBM" SMODEL=`$GREP "platform string" /proc/cpuinfo | cut -d ":" -f 2 | \ $SED -e 's/^[[:space:]]*//' -e 's/[0-9][0-9][0-9] MHz//' \ -e 's/[0-9][0-9] MHz//' -e 's/[0-9][0-9][0-9][0-9] MHz//' \ -e 's/[[:space:]]*$//'` elif [ "$ARCHTYPE" = "s390" ]; then SVENDOR=`$GREP "vendor_id" /proc/cpuinfo | cut -d ":" -f 2 | \ $SED -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'` SMODEL=`$GREP "machine =" /proc/cpuinfo | tail -n1 | cut -d "=" -f 4 | \ $SED -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'` else # assume x86 if [ -n "$DMIDECODE" ]; then T=`$DMIDECODE -t system 2>/dev/null` SVENDOR=`echo "$T" | $GREP 'Manufacturer:' | cut -f2 -d: | \ $SED -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,'` SMODEL=`echo "$T" | $GREP 'Product Name:' | cut -f2 -d: | \ $SED -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,'` fi [ -n "$SVENDOR" ] || SVENDOR="Unknown Vendor" [ "$SVENDOR" != "System Manufacturer" ] || SVENDOR="Unknown Vendor" [ -n "$SMODEL" ] || SMODEL="Unknown Model" [ "$SMODEL" != "System Name" ] || SMODEL="Unknown Model" fi printf "$HEADFMT" "System Configuration" \ "\"$SVENDOR\" \"$ARCHTYPE\" \"$SMODEL\"" # System board info if [ -n "$DMIDECODE" ]; then $DMIDECODE -t baseboard 2>/dev/null | \ $SED -r -e 's,^[[:space:]]*,,' -e 's,:[[:space:]]*,:,' | \ $AWK -F: -v FMT="$HEADFMT" ' BEGIN { COUNT=0 } { if (NF < 2) { next } if ( $1 == "Manufacturer") { COUNT++ ; MANU=$2 } else if ($1 == "Product Name" ) { COUNT++ ; PROD=$2 } else if ($1 == "Version" ) { COUNT++; VERS=$2 } else if ($1 == "Serial Number" ) { COUNT++; SN=$2 } } END { if (COUNT > 0) { printf(FMT, "System board" , "\"" PROD "\" \"" VERS "\" \"" SN "\" \"" MANU "\"") } }' fi # System clock FREQ=`dmesg |$GREP "System clock frequency" | cut -d " " -f 7` if [ -z "$FREQ" ]; then [ -n "$DMIDECODE" ] && \ FREQ=`$DMIDECODE -t processor 2>/dev/null | \ $GREP 'External Clock' | tail -1 | cut -f3 -d " "` [ -n "$FREQ" ] || FREQ="???" fi printf "$HEADFMT" "System clock frequency" "$FREQ MHz" # Physical Memory if [ -n "$DMIDECODE" ]; then MEM=`$DMIDECODE -t 6 2>/dev/null | $AWK 'BEGIN { MEM=0 } /Installed Size: [0-9]+/ { MEM = MEM + $3 } END { print MEM }'` fi [ -z "$MEM" -o "$MEM" = "0" ] && \ MEM=`$AWK '/^MemTotal/ { print "~ " $2/1024 }' /proc/meminfo` printf "$HEADFMT" "Memory size" "$MEM MB" } PrintCpuInfo() { print " ==================================== CPUs ====================================" $SED -e 's,[[:space:]]*:[[:space:]]*,:,' /proc/cpuinfo | \ $AWK -F: -v ARCH="$ARCHTYPE" ' function rep(c, n) { S="" ; for (i=1; i<=n; i++) { S = S "" c } ; return S } BEGIN { COUNT = 0 ; FMT="%3s %-8s %-8s %-8s %s\n" } { if (ARCH ~ "sparc") { if ($1 == "cpu" ) { MODEL[1]=$2 } else if ( $1 ~ "Cpu[0-9]*Bogo" ) { COUNT++ CPU[COUNT] = substr($2,4, length($2) - 7) BOGO[COUNT] = $2 } else if ( $1 ~ "Cpu[0-9]*ClkTck") { HZ="0x" $2 MHZ[COUNT] = HZ / 1000000 } } else if ( ARCH == "alpha" ) { if ($1 == "cpu" ) { TCPU=$2 } else if ($1 == "cpu model") { CPU[1] = TCPU " " $2 } else if ($1 ~ "^cycle frequency") { MHZ[1] = $2 / 1000000 } else if ($1 == "BogoMIPS" ) { BOGO[1] = $2 } else if ($1 == "cpus active") { COUNT = $2 } } else if ( ARCH == "s390" ) { if ($1 == "# processors") { COUNT = $2 } else if ( $1 == "bogomips per cpu" ) { BOGO[1] = $2 } else if ( $1 == "version" ) { MODEL[1] = $2 } } else { if ( $1 == "processor" ) { COUNT++ ; CPU[COUNT]=$2 } else if ( $1 == "model name" ) { MODEL[COUNT]=$2 } else if ( $1 == "cpu MHz" ) { MHZ[COUNT]=$2 } else if ( $1 == "cache size" ) { CACHE[COUNT]=$2 } else if ( $1 == "bogomips" ) { BOGO[COUNT]=$2 } } } END { if (COUNT < 1) { print "*** No CPU info found ***" exit 0 } printf(FMT, "CPU", "Freq", "Cache", "Bogomips", "CPU Implementation") printf(FMT, rep("-",3) , rep("-",8), rep("-",8), rep("-",8), rep("-",32)) for (i=1 ; i <= COUNT; i++) { if (ARCH == "alpha") { VCPU = i VMHZ = MHZ[1] VCACHE = CACHE[1] VBOGO = BOGO[1] VMODEL = MODEL[1] } else if ( ARCH ~ "sparc" ) { VCPU = CPU[i] VMHZ = MHZ[i] VCACHE = CACHE[i] VBOGO = BOGO[i] VMODEL = MODEL[1] } else if (ARCH == "s390" ) { VCPU = i VMHZ = "variable" VCACHE = CACHE[1] VBOGO = BOGO[1] VMODEL = MODEL[1] } else { VCPU = CPU[i] VMHZ = MHZ[i] VCACHE = CACHE[i] VBOGO = BOGO[i] VMODEL = MODEL[i] } printf(FMT, VCPU, VMHZ, VCACHE, VBOGO, VMODEL) } } ' } PrintPciInfo() { print " ================================= IO Devices =================================" if [ -n "$BIOSDECODE" ]; then SLOTINFO=`$BIOSDECODE 2>/dev/null | $GREP 'Slot Entry' | \ $SED -e 's,^.*ID ,SlotNum:,' -e 's/, slot number /:/' \ -e 's/, on-board/:MB/'` fi if [ -n "$LSPCI" ]; then PCIINFO=`$LSPCI -vmm 2>/dev/null | \ $EGREP '^(Slot|Class|Vendor|Device|ProgIf):' | \ $SED -r -e 's,:[[:space:]]*,:,' \ -e '/^Class:/ { s,[[:space:]]*controller,,i ; s,Multimedia[[:space:]]*([a-zA-Z][a-zA-Z]*),\1, ; s,audio,Audio, ; s,video,Video,}' \ -e '/^Class:(RAM|SCSI|VGA|FireWire)/ s,[[:space:]].*,,' \ -e '/^Device:[0-9][0-9]:/ s,^Device,Slot,'` CAPA=`$LSPCI -v 2>/dev/null | $SED -e 's,^[[:space:]]*,,' \ -e '/^[0-9a-f][0-9a-f]:/ { s,^,Slot:, ; s,[[:space:]],: , }' \ -e '/^Slot:/ { s,:[[:space:]].*prog-if[^[]*\[,:, ; s,].*$,:, ; s,[[:space:]].*,, }' \ -e '/^Capabilities:/ s,:[[:space:]]*\[[^]]*\][[:space:]]*,:,' \ -e 's,:[[:space:]]*,:,' | \ $EGREP '^(Slot|Flags|Capabilities):'` fi if [ -z "$SLOTINFO" -a -z "$PCIINFO" -a -z "$CAPA" ]; then print "***** Nothing found! *****" else print "${SLOTINFO}\n${PCIINFO}\n${CAPA}" | $AWK -F: ' function rep(c, n) { S="" ; for (i=1; i<=n; i++) { S = S "" c } ; return S } BEGIN { SLOT="-1" ; COUNT=0 ; SLOTCOUNT=0 } { if ($1 == "SlotNum") { SNO[$2 ":" $3] = $4 ; SLOTCOUNT++ } else if ($1 == "Slot") { SLOT=$2 ":" $3 if (MEM[SLOT] != 1) { SLOTS[COUNT] = SLOT COUNT++ MEM[SLOT] = 1 } else if ( NF > 3 && $4 ) { PIF[SLOT] = $4 } } else if ($1 == "Class") { CLASS[SLOT] = $2 } else if ($1 == "Vendor") { VENDOR[SLOT] = $2 } else if ($1 == "Device") { DEVICE[SLOT] = $2 } else if ($1 == "Flags") { if ( $2 ~ "66MHz" ) { MHZ[SLOT] = "66" } else { MHZ[SLOT] = "33" } } else if ($1 == "Capabilities" && ( $2 ~ "AGP" || DEVICE[SLOT] ~ "AGP")) { BUS[SLOT] = "AGP" } } END { if (COUNT < 1) { exit 0 } FMT="%-4s %-4s %-6s %-13s %s\n" printf(FMT, "Bus" , "Freq", "Slot", "Class +", "Vendor +") printf(FMT, "Type", "MHz" , "" , "ID" , "Model") printf(FMT, rep("-",4), rep("-",4) , rep("-",6), rep("-",13), rep("-",32)) for (i=0 ; i < COUNT; i++) { SLOT = SLOTS[i] if (CLASS[SLOT] ~ " bridge|RAM") { continue } if ( BUS[SLOT] == "AGP" ) { TYPE="agp" } else { TYPE="pci" } if ( MHZ[SLOT] == "" ) { MHZ[SLOT] = "??" } IDX=substr(SLOT,0,5) if ( SNO[IDX] ) { if ( SNO[IDX] == "MB" ) { SLOTNO="MB" } else { SLOTNO=toupper(TYPE) SNO[IDX] } } else if ( TYPE == "agp" ) { SLOTNO="AGP" } else if (SLOTCOUNT > 0) { SLOTNO="MB" } else { # probably permission for biosdecode denied SLOTNO="" } if ( CLASS[SLOT] == "SMBus" ) { TYPE="sm" SLOTNO="MB" } if (PIF[SLOT] ~ "HCI") { TYPE2=PIF[SLOT] } else { TYPE2="" } # tbd resolve PIF and add to CLASS printf(FMT, TYPE , MHZ[SLOT] , SLOTNO, CLASS[SLOT], VENDOR[SLOT]) printf(FMT, TYPE2 , "" , "" , SLOT , DEVICE[SLOT]) print "" } }' fi } PrintIdeInfo() { print " ================================ IDE Devices =================================" # sysfs is missing major information - so we need to use procfs [ -d /proc/ide ] && \ MODELS=`find /proc/ide -type f -name model | $EGREP '/hd[a-z]' | sort` if [ -z "${MODELS}" ]; then print "*** No IDE devices found! ***" else FMT="%-6s %-9s %-6s %-13s %-16s %s\n" printf "$FMT" "Host" "Channel" "Device" "Vendor" "Model" "Type" printf "$FMT" "------" "---------" "------" "-------------" \ "----------------" "----------------" for MODEL in $MODELS ; do ICP=${MODEL%/*} IMEDIA=`cat ${ICP}/media | tr '[[:lower:]]' '[[:upper:]]'` [ "$IMEDIA" = "CDROM" ] && IMEDIA="CD-ROM" [ "$IMEDIA" = "DISK" ] && IMEDIA="PATA HDD" IVENDOR=`cut -d " " -f 1 $MODEL` IMODEL=`cut -d " " -f 2- $MODEL` ICHAN=${ICP##*/} IHOST=${ICP%/*} IHOST=${IHOST##*/} if [ -r "${ICP}/capacity" ]; then ST=$(<${ICP}/capacity) S=$((ST*512)) if [ "$S" -gt 0 ]; then IDX=0 while [ "${S}" -ge 1000.0 ]; do S=$(($S/1024.0)) IDX=$((IDX+1)) done SIZE=$(printf "%1.1f %s " "$S" "${UNITS[$IDX]}" ) else SIZE="" fi else SIZE="" fi # If the model is blank, assume the model is the vendor if [ -z "$IMODEL" ]; then IMODEL="$IVENDOR" IVENDOR="" fi # If the model == vendor, assume the model is the vendor if [ "$IMODEL" = "$IVENDOR" ]; then IMODEL="$IVENDOR" IVENDOR="" fi if [ -z "$IVENDOR" ]; then if [ "$IMODEL" != ${IMODEL#ST} ]; then IVENDOR="Seagate" elif [ "$IMODEL" != ${IMODEL#IC} ]; then IVENDOR="IBM" fi fi printf "$FMT" "$IHOST" "$ICHAN" "$ICHAN" \ "$IVENDOR" "$IMODEL" "${SIZE}$IMEDIA" done fi } function PrintScsiInfo { if [[ ${ARCHTYPE} == "s390" ]]; then print ' ================================ DASD Devices ================================' if [[ ! -f /proc/dasd/devices ]]; then DASDCHANFOUND=false else cat /proc/dasd/devices fi else print ' ================================ SCSI Devices ================================' [[ -d /sys/class/scsi_device ]] && \ SDEVS=${ ls -d /sys/class/scsi_device/*:* 2>/dev/null | sort ; } if [[ -z ${SDEVS} ]]; then print '*** No SCSI devices found! ***' else typeset FMT='%-6s %2s %2s %3s %-6s %-13s %-16s %-16s %s\n' printf "${FMT}" 'Host' 'Ch' 'Id' 'LUN' 'Device' \ 'Vendor' 'Model' 'SAS-Address' 'Type' printf "${FMT}" '------' '--' '--' '---' '------' \ '-------------' '----------------' '----------------' '----------------' typeset TARGET HOST CH ID LUN X TYPENO MODEL VENDOR TYPE DEV SIZE MODULE ST SAS float S # see /usr/include/scsi/scsi.h: DEVICE TYPES typeset -a STYPES=( 'SCSI HDD' 'TAPE' '' 'External Processor/HP Scanner' 'WORM' 'CD-ROM' 'SCANNER' 'MOD' 'MEDIA CHANGER' ) for SDEV in ${SDEVS} ; do TARGET=${SDEV##*/} typeset -a T=( ${TARGET//:/ } ) HOST=${T[0]} CH=${T[1]} ID=${T[2]} LUN=${T[3]} X=$(<$SDEV/device/type) TYPENO=${X%%*( )} if [[ ${TYPENO} == '13' ]]; then TYPE='ENCLOSURE' else TYPE=${STYPES[${TYPENO}]} fi X=$(<$SDEV/device/model) MODEL=${X%%*( )} X=$(<$SDEV/device/vendor) VENDOR=${X%%*( )} if [[ ${VENDOR} == 'ATA' ]]; then VENDOR=${MODEL%% *} if [[ ${VENDOR} == ${MODEL} ]]; then if [[ ${VENDOR} != ${VENDOR#ST} ]]; then VENDOR='Seagate' elif [[ ${VENDOR} != ${VENDOR#IC} ]]; then VENDOR='IBM' fi fi TYPE='SATA HDD' fi # displaying all /dev/* would be e.g. for tapes too much - # one is enough. Also prefer none-generic devices ... if [[ ${TYPE: -3:3} == 'HDD' ]]; then [[ -d ${SDEV}/device/block ]] && \ X=${ ls -1d ${SDEV}/device/block/* 2>/dev/null | head -1 ; } fi [[ -z $X ]] && X=${ ls -1d ${SDEV}/device/*:* 2>/dev/null| \ ${EGREP} -v '/scsi_(device|generic):' | sort | \ head -1 ; } [[ -z $X ]] && X=${ ls -1d ${SDEV}/device/scsi_generic:* 2>/dev/null | head -1 ; } DEV=${X##*:} ; DEV=${X##*/} if [[ -n ${DEV} && -r "${SDEV}/device/block:${DEV}/size" ]]; then ST=$(<$SDEV/device/block:$DEV/size) S=$((ST*512)) if (( S > 0 )); then integer IDX=0 while (( S >= 1000.0 )); do (( S/=1024.0 )) (( IDX++ )) done SIZE=${ printf '%1.1f %s ' "$S" "${UNITS[${IDX}]}" ; } else SIZE='' fi else SIZE="" fi [[ -f ${SDEV}/device/sas_address ]] && SAS=$(<${SDEV}/device/sas_address) || SAS='' MODEL=${MODEL#* } MODULE=$(< /sys/class/scsi_host/host${HOST}/proc_name) case ${MODULE} in usb-storage) TYPE='USB STORAGE' ;; sata*) TYPE='SATA HDD' ;; esac printf "${FMT}" "scsi${HOST}" "${CH}" "${ID}" "${LUN}" "${DEV}" \ "${VENDOR}" "${MODEL}" "${SAS#0x}" "${SIZE}${TYPE}" done fi fi } PrintMemoryInfo() { print "\n============================ Memory Configuration ============================" if [ -n "$DMIDECODE" ]; then $DMIDECODE -t 17 -t 20 | \ $SED -e 's,^[[:space:]]*,,' -e 's,:[[:space:]]*,:,' \ -e 's,[[:space:]]*$,,' | $AWK -F: ' BEGIN { COUNT=0 ; HANDLE="-1" } { # "" may indicate an update problem, displat always if ( $1 ~ "^Handle" && $1 ~ "DMI type 17" ) { HANDLE=substr($1,8,6) HANDLES[COUNT] = HANDLE COUNT++ } else if ( $1 == "Size" ) { SIZE[HANDLE] = $2 } else if ( $1 == "Form Factor" ) { FORM[HANDLE] = $2 } else if ( $1 == "Locator") { LOC[HANDLE] = $2 } else if ( $1 == "Bank Locator" ) { BANK[HANDLE] = $2 } else if ( $1 == "Type" && $2 != "Unknown" && $2 != "Other") { TYPE[HANDLE] = $2 } else if ( $1 == "Type Detail" && $2 != "Unknown" && $2 != "Other" \ && $2 != "None" ) { TYPEDETAIL[HANDLE] = $2 } else if ( $1 == "Starting Address" ) { TSTART=$2 } else if ( $1 == "Ending Address" ) { TEND=$2 } else if ($1 == "Physical Device Handle") { HANDLE=$2 ASTART[HANDLE] = TSTART AEND[HANDLE] = TEND } } END { if (COUNT < 1) { print "*** No memory information available *** " exit 0 } FMT = "%13s %7s %-10s %s\n" printf(FMT, "Base Address ", "Size ", "Location", "Type") printf(FMT, "-------------", "-------", "----------", "----------------") for (i=0; i < COUNT ; i++) { HANDLE=HANDLES[i] if ( SIZE[HANDLE] == "No Module Installed" ) { continue } if (LOC[HANDLE]) { L = LOC[HANDLE] } else { L = BANK[HANDLE] } T="" N=0 if (FORM[HANDLE]) { T=FORM[HANDLE] " " } if (TYPE[HANDLE] ) { T=T TYPE[HANDLE] " " } if (TYPEDETAIL[HANDLE] ) { T=T TYPEDETAIL[HANDLE] } printf(FMT, ASTART[HANDLE], SIZE[HANDLE], L, T) } } ' else print "*** No memory information available *** " fi } function PrintSensorInfo { typeset TPATH SENSOR TARGET NO NAME CNAME X T Z VALUE typeset -a CNAMES typeset -F FACTOR print ' ============================ Environmental Status ============================' # FANs [[ -d /sys/class/hwmon ]] && \ typeset FANS=${ find /sys/class/hwmon -follow -maxdepth 3 \ -name 'fan[[:digit:]]*_input' 2>/dev/null | sort ; } if [[ -z ${FANS} ]]; then print '*** No fans found ***' else typeset HFMT='%-10s %6s %s\n' typeset FMT='%-10s %6d %s\n' printf "${HFMT}" 'Sensor' ' RPM ' 'Source' printf "${HFMT}" '----------' '------' '----------------' typeset FAN FDIV typeset -F SPEED for FAN in ${FANS} ; do TPATH=${FAN%/*} SENSOR=$(<$TPATH/name) TARGET=${FAN##*/} NO=${TARGET#fan} NO=${NO%_input} FDIV="${TPATH}/fan${NO}_div" NO=$((NO-1)) X="${FAN_IGNORE[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) [[ -n ${CNAMES[${NO}]} ]] && continue fi SPEED=$(<${FAN}) # Not reliable: On some systems it is already taken into account, on others not # Adjust via FAN_FACTOR in prtdiag.conf, if neccesarry # if [ -r "$FDIV" ]; then # D=$(<$FDIV) # [ -n "$D" ] && SPEED=$((SPEED/D)) # fi NAME="Fan ${NO}" X="${FAN_SRC[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) CNAME=${CNAMES[${NO}]} [[ -n ${CNAME} ]] && NAME=${CNAME} fi X="${FAN_FACTOR[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) FACTOR=${CNAMES[${NO}]} (( FACTOR )) && (( SPEED*=FACTOR )) fi X="${FAN_OFFSET[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) FACTOR=${CNAMES[$NO]} (( SPEED+=FACTOR )) fi printf "$FMT" "$SENSOR" "$SPEED" "$NAME" done fi # Temperatures [[ -d /sys/class/hwmon ]] && \ typeset TEMPS=${ find /sys/class/hwmon -follow -maxdepth 3 \ -name 'temp[[:digit:]]*_input' 2>/dev/null | sort ; } if [[ -z ${TEMPS} ]]; then print '*** No temperature sensors found ***' else typeset HFMT='%-10s %-6s %s\n' typeset FMT='%-10s %6.1f %s\n' SUFFIX="°C" [[ -z ${CELSIUS} ]] && SUFFIX="°F" typeset -F DEGREES print printf "${HFMT}" 'Sensor' " ${SUFFIX} " 'Source' printf "${HFMT}" '----------' '------' '----------------' for T in ${TEMPS} ; do TPATH=${T%/*} if [[ -f ${TPATH}/name ]]; then SENSOR=$(<${TPATH}/name) elif [[ -f ${TPATH}/i2c-0/name ]]; then SENSOR=$(<${TPATH}/i2c-0/name) else SENSOR='unknown' fi TARGET=${T##*/} NO=${TARGET#temp} NO=${NO%_input} (( NO-- )) SENSOR=${SENSOR// /_} X="${TEMP_IGNORE[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) [[ -n ${CNAMES[${NO}]} ]] && continue fi VALUE=$(<$T) [[ -z ${CELSIUS} ]] && (( DEGREES=VALUE*9/5000.0+32.0 )) \ || (( DEGREES=VALUE/1000.0 )) NAME="Temp ${NO}" X="${TEMP_SRC[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) CNAME=${CNAMES[$NO]} [[ -n ${CNAME} ]] && NAME=${CNAME} fi X="${TEMP_FACTOR[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) FACTOR=${CNAMES[${NO}]} (( FACTOR )) && (( DEGREES*=FACTOR )) fi X="${TEMP_OFFSET[$SENSOR]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) FACTOR=${CNAMES[${NO}]} (( FACTOR )) && (( DEGREES+=FACTOR )) fi printf "${FMT}" "${SENSOR}" "${DEGREES}" "${NAME}" done fi # Voltage [[ -d /sys/class/hwmon ]] && \ typeset VOLTS=${ find /sys/class/hwmon -follow -maxdepth 3 \ -name 'in[[:digit:]]*_input' 2>/dev/null | sort ; } if [[ -z ${VOLTS} ]]; then print '*** No voltage sensors found ***' else typeset -a SRC=( 'CPU #1 (Vcor1)' 'CPU #2 (Vcor2)' '+3.3V' '+5V' '+12V' '-12V' '-5V' 'Standby' 'Battery' ) typeset HFMT='%-10s %6s %s\n' typeset FMT='%-10s %6.2f %s\n' typeset -F VOLT print printf "${HFMT}" 'Sensor' ' Volt ' 'Source' printf "${HFMT}" '----------' '------' '----------------' for T in ${VOLTS} ; do TPATH=${T%/*} SENSOR=$(<$TPATH/name) TARGET=${T##*/} NO=${TARGET#in} NO=${NO%_input} X="${VOLT_IGNORE[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) [[ -n ${CNAMES[${NO}]} ]] && continue fi VALUE=$(<$T) NAME=${SRC[${NO}]} [[ -z ${NAME} ]] && NAME="in${NO}" X="${VOLT_SRC[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) CNAME=${CNAMES[$NO]} [[ -n ${CNAME} ]] && NAME=${CNAME} fi VOLT=$((VALUE/1000.0)) X="${VOLT_FACTOR[${SENSOR}]}" if [[ -n $X ]]; then CNAMES=( ${X//,/ } ) FACTOR=${CNAMES[$NO]} (( FACTOR )) && (( VOLT*=FACTOR )) fi X="${VOLT_OFFSET[${SENSOR}]}" if [ -n $X ]; then CNAMES=( ${X//,/ } ) FACTOR=${CNAMES[${NO}]} (( FACTOR )) && (( VOLT+=FACTOR )) fi printf "${FMT}" "${SENSOR}" "${VOLT}" "${NAME}" done fi } PrintBiosInfo() { print " ============================ BIOS/PROM Information ===========================" if [ -n "$DMIDECODE" ]; then $DMIDECODE -t bios 2>/dev/null | $EGREP '(Vendor|Version|Date):' | \ $SED -e 's,^[[:space:]]*, ,' else print "*** No BIOS information available" fi } VERS="${.sh.version}" if [[ ! "${VERS}" =~ \s93 ]]; then echo " WARNING: This is not a ksh93 from AT&T Research! Neither bash nor pdksh, etc. are kompatible to ksh93. So this program will probably produce errors and may not display the results you want. Download and install the appropriate package from your Linux distribution or direct via http://www.research.att.com/~gsf/download/ ! " fi function Usage { print -u2 'Usage: prtdiag [-f] [-h] [-H] [-V] [-t types ] Display diagnostic information about the current system. -f .. display temperature values in °F instead of °C -h .. display this help and exit -H .. do not print the report header (i.e. hostname and time of report) -V .. display the version of this tool and exit -t types .. a string of letters, which dictate, what information should be displayed. Following types are available: g .. general information c .. information about CPUs p .. PCI/Input/Output devices related information i .. IDE devices information s .. SCSI devices information m .. memory related information e .. environmental status (fan/temperature/voltage) b .. BIOS information a .. display everything (i.e. cpmebisg) -T fnlist a comma separated list of function names - trace on execution. ' } CELSIUS=1 SH_RHEAD=1 SH_TYPES='gcpismeba' while getopts 'fhHVt:T:' opt; do case $opt in f) CELSIUS="" ;; h) Usage ; exit 1 ;; H) SH_RHEAD="" ;; V) PrintVersion ; exit 1 ;; t) [ "$OPTARG" = "a" ] || SH_TYPES="$OPTARG" ;; T) typeset -ft ${OPTARG//,/ } ;; esac done shift $(($OPTIND-1)) ARCHTYPE=${ uname -m ; } typeset -a UNITS=( B KiB MiB GiB TiB PiB EiB ZiB YiB ) LoadCustomizations CheckEnvironment [ -z "$SH_RHEAD" ] || PrintReportHead [ "${SH_TYPES//g}" == ${SH_TYPES} ] || PrintGeneralInfos [ "${SH_TYPES//c}" == ${SH_TYPES} ] || PrintCpuInfo [ "${SH_TYPES//p}" == ${SH_TYPES} ] || PrintPciInfo [ "${SH_TYPES//i}" == ${SH_TYPES} ] || PrintIdeInfo [ "${SH_TYPES//s}" == ${SH_TYPES} ] || PrintScsiInfo [ "${SH_TYPES//m}" == ${SH_TYPES} ] || PrintMemoryInfo [ "${SH_TYPES//e}" == ${SH_TYPES} ] || PrintSensorInfo [ "${SH_TYPES//b}" == ${SH_TYPES} ] || PrintBiosInfo print ""