#!/usr/bin/perl #--------------------------------------- # # Original Version # ---------------- # http://www.Linux-1U.net/LCD/scripts/record_sensors.pl # # # record-sensors.pl - read/dissplay data from sensors # # read sensor data from /proc/sys/dev/sensors/*/* # convert units and display to an LCD panel connected to # a serial port (on ttyS*) # also read other info from the /proc filesystem # and display it to the LCD panel # in a sensible format # # this version includes support for these LCD panels: # 2*16 text using the Scott Edwards serial adapter # 4*40 Orbital Matrix integrated serial display # Scott Edwards Graphics LCD (in text mode only) # (primitive) display to /dev/tty6 # # this version includes support for these motherboards # SuperMicro SEA370 # ASUS MEW # # written by Ray Olszewski # begun February 4, 2000 # this version current as of May 07, 2000 #--------------------------------------- # --- edit the following section to select which options # --- the running version will use # --- initialization section # how long do you want to pause between tests? # $sleeptime = 2 ; $sleeptime = 3 ; # $sleeptime = 4 ; # $sleeptime = 5 ; # which serial port is the display attached to? # $SERIALPORT = "/dev/ttyS0" ; $SERIALPORT = "/dev/ttyS1" ; # which LCD panel are you going to use? Run the appropriate sub # se_text () ; se_graphics() ; # orbital_matrix() ; # console_display() ; # which motherboard are you using? Run the appropriate sub # SuperMicro_SEA370() ; ASUS_MEW() ; # unsupported() ; # --- end of initialization section # -- main loop # uncommment the tests you actually want to run # change the order as you like # one per mothrboard - match the choice made above while (1) { # SuperMicro_SEA370_sensor_check() ; ASUS_MEW_sensor_check() ; # non-motherboard-sppecific tests cpu_check() ; uptime_check() ; memory_check ; filesystem_check() ; nic_check() ; route_check() ; login_check() ; time_check() ; key_apps_check() ; } ; # end main loop #------------------------------------------------------ # You shouldn't need to edit below here to get it wotking # These are the subs that the above lines call # ----------------------------------------------------- sub ASUS_MEW { # these values are specific to the ASUS NEW board # and include only the VALID sensor values that it # reports -- based on examination of the BIOS display $sensorpath = "/proc/sys/dev/sensors/as99127f-i2c-0-2d/" ; @sensornames = ( "in0", "in2", "in3", "in4", "in5", "in6", "fan1", "fan2", "fan3", "temp1", "temp2" ) ; @sensorlabels = ( "VCore1", "+3.3V", "+5V", "+12V", "-12V", "-5V", "CPU fan", "p/s fan", "case fan", "mbd temp", "CPU temp" ) ; } ; # end sub ASUS_MEW sub SuperMicro_SEA370 { # these values are specific to the SuperMicro 370SEA board # and include only the VALID sensor values that it # reports -- based on examination of the board docs # (not quite correct) and the BIOS display (assumed to # be correct) $sensorpath = "/proc/sys/dev/sensors/w83627hf-isa-0290/" ; @sensornames = ( "in0", "in2", "in3", "in4", "in5", "fan1", "fan2", "fan3", "temp1" ) ; @sensorlabels = ( "VCore1", "+3.3V", "+5V", "+12V", "-12V", "CPU fan", "case fan", "backup fan", "CPU temp" ) ; } ; # end sub SuperMicro_SEA370 # the LCD stuff ---------------------------------------- sub se_text { # set up the serial port for output # SE board can be set to 2400 or 9600 bps print "init serial porti\n" ; system ("stty 9600 <$SERIALPORT") ; open (LCDOUT,">$SERIALPORT") ; # LCD codes for this serial adapter $lcdcmd = "\xFE" ; # generel command prefix $cls = $lcdcmd."\x01" ; # clear display $cursoron = $lcdcmd."\x14" ; # underline cursor $curesorblock = $lcdcmd."\x13" ; # block cursor $cursoroff = $lcdcmd."\x12" ; # make cursor invisible $cursorleft = $lcdcmd."\x16" ; # move cursor one position to left $cursorright = $lcdcmd."\x20" ; # move cursor one position to right $cursorhome = $lcdcmd."\x02" ; $line2 = $lcdcmd."\xC0" ; # go to start of second line $screenoff = $lcdcmd."\0x08" ; # blank screen but do not clear $screenon = $lcdcmd."\0x12" ; # restore blanked screen, cursor hidden # Clear and home the LCD display print LCDOUT "$cls \n" ; print LCDOUT "$cursorhome\n" ; # make the cursor invisible print LCDOUT "$cursoroff\n" ; } ; # end sub se_text ; sub orbital_matrix { print "Initialize Orbital Matrix display\n" ; system ("stty 19200 <$SERIALPORT") ; open (LCDOUT,">$SERIALPORT") ; # the special LCD codes (for the Orbital Matrix display/controller) $lcdcmd = "\xFE" ; $wrapon = $lcdcmd."C" ; $wrapoff = $lcdcmd."D" ; $scrollon = $wrapon."Q" ; $scrolloff = $lcdcmd."R" ; $blinkon = $lcdcmd."S" ; $blinkoff = $lcdcmd."T" ; $cls = $lcdcmd."X"."\n".$lcdcmd."H" ; $cursoron = $lcdcmd."J" ; $cursoroff = $lcdcmd."K" ; $cursorleft = $lcdcmd."L" ; $cursorright = $lcdcmd."M" ; $cursorhome = $lcdcmd."H" ; $gotoxy = $lcdcmd."G" ; # follow by column-number row-number $line2 = $gotoxy."\x01"."\x02" ; # clear and home the display print LCDOUT "$wrapon" ; print LCDOUT "$cls" ; } ; # end sub orbital_matrix sub se_graphics { system ("stty 9600 <$SERIALPORT") ; open (LCDOUT,">$SERIALPORT") ; # runs the SE greaphics LCD in text mode only # define only the essentials for this one $lcdcmd = "" ; $cls = "\x0c"."\x01" ; #clear and home $line2 = "\x0d" ; # regular CR $lighton = "\x0e" ; $lightoff = "\x0f" ; print LCDOUT "$lighton" ; print LCDOUT "cls\n" } ; # end sub se_graphics sub console_display { open (LCDOUT,">/dev/tty6") ; $lcdcmd = "" ; $cls = "\r" ; $line2 = "\r" ; } ; # end sub console_display # the actual tests ------------------------------------- sub ASUS_MEW_sensor_check { print LCDOUT "$cls ASUS MEW board\n" ; sleep $sleeptime ; $whichone = 0 ; # this is the sensors part of the cycle for ( $whichone = 0 ; $whichone <= 10 ; $whichone++ ) { open (READING,"$sensorpath/$sensornames[$whichone]") ; $rawvalue = ; close READING ; @pieces = split(/ /,$rawvalue) ; $dispvalue = "" ; # now do sensor-specific scaling and settings # conversion rules taken from /etc/sensors.conf values # for the w83782d (0-4) and w83781d (5-6) chip # -- accuracy not guaranteed by me (RO) # these are the voltages if ( $whichone == 0 ) { $dispvalue = 1 * @pieces[2] ; } elsif ( $whichone == 1 ) { $dispvalue = 1 * @pieces[2] ; } elsif ( $whichone == 2 ) { $dispvalue = @pieces[2] * ( ( 6.8 / 10 ) + 1 ) ; } elsif ( $whichone == 3 ) { $dispvalue = @pieces[2] * ( ( 28 / 10 ) + 1 ) ; } elsif ( $whichone == 4 ) { $dispvalue = @pieces[2] * ( -210 / 60.4 ) ; } elsif ( $whichone == 5 ) { $dispvalue = @pieces[2] * ( - 90.9 / 60.4 ) ; } # this is the fan group elsif ( $whichone == 6 || $whichone == 7 || $whichone == 8 ) { @pieces[1] = 1 * @pieces[1] ; $dispvalue = @pieces[1]." RPM" ; } # this is the temperature group elsif ( $whichone == 9 || $whichone == 10 ) { @pieces[3] = @pieces[2] * ( 9 / 5 ) + 32 ; @pieces[2] = 1 * @pieces[2] ; $dispvalue = @pieces[2]."C/".@pieces[3]."F" ; } else { $dispvalue = "****ERROR****" ; } ; # clear and center $dispvalue = sprintf("%.2f",$dispvalue) ; print "$whichone @sensorlabels[$whichone] $dispvalue\n" ; print LCDOUT "$cls @sensorlabels[$whichone] \n" ; print LCDOUT "$line2 $dispvalue \n" ; #print LCDOUT "$cls Hardware Sensor $line2" ; # print LCDOUT "$sensorlabels[$whichone]: $dispvalue\n" ; sleep $sleeptime ; } ; # end the sensors block } ; #end ASUS_MEW_sensor_check ; sub SuperMicro_SEA370_sensor_check { print LCDOUT "$cls SuperMicro SEA370\n" ; sleep $sleeptime ; $whichone = 0 ; # this is the sensors part of the cycle for ( $whichone = 0 ; $whichone <= 8 ; $whichone++ ) { open (READING,"$sensorpath/$sensornames[$whichone]") ; $rawvalue = ; close READING ; @pieces = split(/ /,$rawvalue) ; $dispvalue = "" ; # now do sensor-specific scaling and settings # conversion rules taken from /etc/sensors.conf values # for the w83627 chip -- accuracy not guaranteed by me (RO) # these are the voltages if ( $whichone == 0 ) { $dispvalue = 1 * @pieces[2] ; } elsif ( $whichone == 1 ) { $dispvalue = 1 * @pieces[2] ; } elsif ( $whichone == 2 ) { $dispvalue = @pieces[2] * ( ( 6.8 / 10 ) + 1 ) ; } elsif ( $whichone == 3 ) { $dispvalue = @pieces[2] * ( ( 28 / 10 ) + 1 ) ; } elsif ( $whichone == 4 ) { $dispvalue = ( @pieces[2] * 5.14 ) - 14.91 ; } # this is the fan group elsif ( $whichone == 5 || $whichone == 6 || $whichone == 7 ) { @pieces[1] = 1 * @pieces[1] ; $dispvalue = @pieces[1]." RPM" ; } # this is the temperature group elsif ( $whichone == 8 ) { @pieces[3] = @pieces[2] * ( 9 / 5 ) + 32 ; @pieces[2] = 1 * @pieces[2] ; $dispvalue = @pieces[2]."C/".@pieces[3]."F" ; } else { $dispvalue = "****ERROR****" ; } ; # clear and center print LCDOUT "$cls $sensorlabels[$whichone] \n" ; print LCDOUT "$line2 $dispvalue \n" ; #print LCDOUT "$cls Hardware Sensor $line2" ; # print LCDOUT "$sensorlabels[$whichone]: $dispvalue\n" ; sleep $sleeptime ; } ; # end the sensors block } ; #end SuperMicro_SEA370_sensor_check ; sub cpu_check { # show CPU utilization info open (READING,"/proc/stat") ; # everything we want is on the first line $rawvalue = ; @pieces = split(/\s+/,$rawvalue) ; $usertime = @pieces[1] + @pieces[2] - $oldusertime ; $systemtime = @pieces[3] - $oldsystemtime ; $idletime = @pieces[4] - $oldidletime ; $totaltime = $usertime + $systemtime + $idletime ; $pctuser = int ( 100 * ( $usertime / $totaltime ) ) ; $pctsystem = int ( 100 * ( $systemtime / $totaltime ) ) ; $pctidle = int ( 100 * ( $idletime / $totaltime ) ) ; # save bases for next round $oldusertime = @pieces[1] + @pieces[2] ; $oldsystemtime = @pieces[3] ; $oldidletime = @pieces[4] ; print LCDOUT "$cls CPU Use $line2" ; print LCDOUT "User time: $pctuser % \n" ; sleep $sleeptime ; print LCDOUT "$cls CPU Use $line2" ; print LCDOUT "System time: $pctsystem % \n" ; sleep $sleeptime ; print LCDOUT "$cls CPU Use $line2" ; print LCDOUT "Idle Time: $pctidle % \n" ; sleep $sleeptime ; } ; # end cpu_check sub uptime_check { # show uptime-style system load @uptime = split ( /\s+/,`uptime` ) ; if ( @uptime[4] eq "days," ) { $upstring = "@uptime[3] @uptime[4] @uptime[5]" } else { $upstring = "0 days, @uptime[3]" } ; chop ($upstring) ; print LCDOUT "$cls System Uptime -- $line2$upstring \n" ; sleep $sleeptime ; } ; #end uptime_check sub memory_check { # show free info (% used RAM, % used swap) open (READING,"/proc/meminfo") ; $rawvalue = ; # get and toss useless first line $rawvalue = ; # the one we actually want $rawvalue2 = ; #and the one for swap close (READING) ; @pieces = split(/\s+/,$rawvalue) ; $realuse = @pieces[2] - @pieces[5] - @pieces[6] ; #buffers/cache $realpct = int ( 100 * ( $realuse / @pieces[1] ) ) ; $realuse = int ( $realuse / 1000 ) ; @pieces = split(/\s+/,$rawvalue2) ; $swapuse = @pieces[2] ; $swappct = int ( 100 * ( $swapuse / @pieces[1] ) ) ; $swapuse = int ( $swapuse /1000 ) ; print LCDOUT "$cls RAM: $realuse K $realpct % $line2" ; print LCDOUT "SWAP: $swapuse K $swappct % \n" ; sleep $sleeptime ; } ; # end memory_check ; sub filesystem_check { # show filesystem utilization # cheating here because perl doesn't have a direct # equivalent to the C "statfs" function call $filedata = `df` ; @filelines = split(/\n/,$filedata) ; for ( $k = 1 ; $k <= 1 ; $k++ ) { @fileinfo = split(/\s+/,@filelines[$k]) ; @fileinfo[1] = int ( @fileinfo[1] / 1000 ) ; @fileinfo[2] = int ( @fileinfo[2] / 1000 ) ; print LCDOUT "$cls @fileinfo[0] $line2" ; print LCDOUT "@fileinfo[4] (@fileinfo[2] K) used \n" ; sleep $sleeptime ; } ; } ; sub nic_check { # check eth* interfaces # this relies on the predictability of ifconfig output @myinterfaces = split( /\n/,`ifconfig`) ; for ( $i = 0 ; $i <= $#myinterfaces ; $i++ ) { @thisline = split( /\s+/,@myinterfaces[$i] ) ; if ( @thisline[0] =~ /eth/ ) { $i++ ; @thisline = split ( /\s+/,@myinterfaces[$i] ) ; ($junk,$ipaddr) = split ( /:/,@thisline[2] ) ; $i++ ; @thisline = split ( /\s+/,@myinterfaces[$i] ) ; $ifstatus = @thisline[1] ; print LCDOUT "$cls $ipaddr$line2$ifstatus \n" ; sleep $sleeptime ; } ; } ; } ; sub route_check { # check connectivity (to default gateway) # assume the default route is the last entry in the routing table @myroutes = split (/\n/,`route -n` ) ; if ( @myroutes[$#myroutes] =~ /UG/ ) { @gateway = split( /\s+/,@myroutes[$#myroutes] ) ; $gateway = @gateway[1] ; $isitthere = system("ping -c 2 $gateway >/dev/null") ; if ( $isitthere == 0 ) { $mymessage2 = "IS pingable" } else { $mymessage2 = "IS NOT pingable" ; } ; } else { $gateway = "no default gateway" ; $mymessage2 = "in routing table" ; } ; print LCDOUT "$cls $gateway $line2$mymessage2 \n"; sleep $sleeptime ; } ; sub login_check { # check for root logins $whosthere = `who` ; if ( $whosthere =~ /root/ ) { $rootcheck = "root IS " } else { $rooteheck = "root IS NOT " } ; print LCDOUT "$cls $rootcheck $line2 logged in \n" ; sleep $sleeptime ; } ; # end login_check sub key_apps_check { $proclist = `ps ax` ; # a bit of self-reference here -- we know this will be running $mymessage1 = "LCD monitor --" ; if ( $proclist =~ /lcd/ ) { $mymessage2 = "IS running" ; } else { $mymessage2 = "IS NOT running" ;} ; print LCDOUT "$cls $mymessage1 $line2$mymessage2 \n" ; sleep $sleeptime ; #and now a dummy one we know won't be running $mymessage1 = "mxyzptlk --" ; if ( $proclist =~ /mxyzptlk/ ) { $mymessage2 = "IS running" ; } else { $mymessage2 = "IS NOT running" ; } ; print LCDOUT "$cls $mymessage1 $line2$mymessage2 \n" ; sleep $sleeptime ; # and now one that moight or might not be running $mymessage1 = "inetd --" ; if ( $proclist =~ /inetd/ ) { $mymessage2 = "IS running" ; } else { $mymessage2 = "IS NOT running" ; } ; print LCDOUT "$cls $mymessage1 $line2$mymessage2 \n" ; sleep $sleeptime ; } ; # end key_apps_check # report time of last backup (NOT IMPLEMENTED) sub time_check { #current date and time - again, done the lazy way @dateandtime = split(/ /,`date`) ; $datepart = @dateandtime[0]." ".@dateandtime[1]." ".@dateandtime[2],", ".@dateandtime[5] ; $timepart = @dateandtime[3]." ".@dateandtime[4] ; print LCDOUT "$cls $datepart $line2 $timepart \n" ; sleep $sleeptime ; } ; # end time_check # should never get here print LCDOUT " EXITING PROGRAM\n" ; print "EXITING PROGRAM\N" ; close LCDOUT ; # EOP