Subject: On sensors and burning up the CPU CHIP
To: None <netbsd-users@netbsd.org>
From: Todd Gruhn <tgruhn2@mail.com>
List: netbsd-users
Date: 09/30/2003 10:18:26
I got the kernel working with APC. Got daemon code
implemented properly. Built rc.d script.
Anyone want to suggest how I can further secure this
daemon? How I can speed it up?

#!/bin/sh
# $NetBSD: snmpd.sh,v 1.3 2001/01/26 02:02:35 hubertf Exp $

#NOTES: This script causes snmpd to put a pid file in /var/run/snmpd
#       I can now start/stop/restart snmpd
#       I modified it to use my config files (come with UCD-SNMP

# REQUIRE: DAEMON
# PROVIDE: stingerd
# BEFORE: LOGIN

# PID file:

PF=/var/run/stingerd.pid


case $1 in
start)
	if [ -x /usr/local/sbin/stingerd ]
	then
	    echo -n ' stingerd'
            /usr/local/sbin/stingerd
	fi
	;;

stop)
	if [ -f ${PF} ]; then
                num=`cat ${PF}`
		pidr=`expr $num + 1`
		 #The REAL PID...
		kill $pidr

	#	kill `cat ${PF}`
		rm -f ${PF}
	else
		echo "$0: stingerd not running or PID not recorded!" 1>&2
	fi
	;;

restart)
	sh $0 stop
	sh $0 start
	;;
*)
	echo "Usage: $0 {start|stop|restart}"
	exit 1
esac



#! /usr/local/bin/perl -w 

## MY SECOND attempt at writing  daemon...
## Watch the CPU temp and FAN rpms lest I get stung by another
## burnt chip... Notify root via email, and shutdown system...

die ("Must be root to execute this script") if ($< && $>);

eval 'exec /usr/local/bin/perl -w -S $0 ${1+"$@"}'
    if 0; # not running under some shell

$ENV{SHELL} = "";           # I set perlman PATH and SHELL for safety reasons
$ENV{PATH} = "/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin";

use Log::Logger;
use Mail::Mailer;
use strict; #restrict unsafe programming; see CAMEL book p. 500

#use Proc::PID::File qw( :all ); #qw(:all);

 use POSIX qw( setsid ) ; 

use vars qw($ppid  $pid); #DECLARE the global vars! SEE CAMEL Book, p. 516

 &become_daemonic();

# Your code here
  if (-e "/var/run/stingerd.pid") 
    {unlink "/var/run/stingerd.pid"}; # GET RID of old pid file

#  pid_file_set( dir => "/var/run", name => "stingerd.pid" );
#          die "Already running!" if pid_file_alive();
#  die "Already running!" if Proc::PID::File->running();


       open(PIDFILE,"+>/var/run/stingerd.pid");
       print PIDFILE $ppid; #was $pid_target;               ## ESTAB. a new PIDFILE
       close PIDFILE;

my $its_time_to_die = 0;

&mv_old_log(); #MOVE the logfile stingerd.log to stingerd.?.gz -- where ? is a number
               #now it wont get run over

###############################################################
my $lh = new Log::Logger;
   $lh ->open ("/var/log/stingerd.log");
   $lh ->log("CPU and FAN readings\n"); #INITIALIZE the log...
   $lh ->log("\n");
###############################################################

my $count = 0;
 while (1) #GENERATE the inf. loop condition
  {
   $count++; #increment $count

my (@ENV_vars, $nums, @numbers, $ts, @ts, $ts2 );

   @ENV_vars = `/usr/sbin/envstat`; ## This is called "BACKTICKING";
                                    ## see CAMEL book, p. 342 

   $nums = $ENV_vars[2];
#   print "\$nums=: $nums\n"; #DIAGNOSTIC CODE

   @numbers = split(/\s+ /,$nums); # MUST BE \s+ !!

   #print "\@numbers=: @numbers\n";

   if ( 0 == ($count % 360 )   ) # IF 0 == ( remainder of $count / 898 ) then ...
     # 898 gives me 1805s between samples/log entries (30min is 1800s) @ sleep = 2
     {

       $ts = localtime;   # ADDED a time stamp here...
       @ts = split /\s+/, $ts;
       shift @ts;

      # @ts2 = @ts[1,2,3,4];

      $ts2 = join(" ",@ts);

     $lh -> log("$ts2" . "     " . "$numbers[1]" . " " . "$numbers[4]");  ##  $ENV_vars[1] is '  ' (leads with a space)

     }
   

   # write data to file...

  #MUST GRAB first set of nums and analyse IMMEDIATELY!

     if ( ($numbers[1] gt 49 )    || ($numbers[4] lt 1700    ) ) 
        {$its_time_to_die = 1; } # reset the flag -- makes the code test able...

     &run_shutdown if ($its_time_to_die); # if 1 ...

    sleep 10; #  Looks right -- cuts CPU load. IF YOU MAKE sleep() too long, 3600s for
              #  instance, and CPU temp goes too high, then it can easily overheat
              #  without ever being detected -- WHAT GOOD WAS THAT!?

  } # close while {}

sub run_shutdown
  {
    use Term::ANSIColor;

    print "\n";
    print color ("bold");
    print color ("red"), "**** CPU hit 49 deg. Centgrade: OVERHEAT CONDITION \n";
    print color ("red"), "     shutting down system... ****",color("reset");
    print color ("reset");

 my $mailer = Mail::Mailer ->new("sendmail");
    $mailer -> open ({ To=> 'root@localhost',
		       Subject=>"System Shutdown",

		     }) or die "Cant open: $!";

print $mailer "Stingerd has noticed a rise in CPU core temp\n";
print $mailer "or a drop below minimum FAN velocity\n";
print $mailer "\n";
print $mailer "I have taken the liberty of shutting down the system\n";
print $mailer "before any damage accurs. PLEASE FIX ME\n";

$mailer -> close();
$lh -> close(); #close logfile


sleep 5; # GIVE the mail a chance to get there...

system "/sbin/shutdown -p now";


  }

sub mv_old_log
  {
#   print "YOUR RUNNING mv_old_log...\n";

chdir "/var/log";

my (@fields, $foo, $last_ele, $last_index, $length, @ls_said, $this_index );

   if ( (-e "/var/log/stingerd.log" ) && (!-e "/var/log/stingerd.0.gz") )
      { 
	rename "/var/log/stingerd.log" , "/var/log/stingerd.0";
	system "/usr/bin/gzip stingerd.0"; #gets us to stingerd.0.gz
      }
   elsif ( (-e "/var/log/stingerd.log" ) && (-e "/var/log/stingerd.0.gz") )
      {
      #  chdir "/var/log"; # were already in /var/log stupid...
        open (PROC, "ls stingerd*gz |"); #ISN'T that the truth???
	@ls_said = <PROC>;
	close PROC;
	$length = (@ls_said);
	$last_ele = $ls_said[$length - 1];
	$last_ele =~ s/[.]/ /g;  #convert . to ' ' RIGHT?
	@fields = split /\s+/, $last_ele;
#print "\@fields =: @fields\n";

	$last_index = $fields[1];
#print "\$last_index =: $last_index\n";
	$this_index = $last_index + 1;

	$foo = "/var/log/stingerd." . $this_index;
#	print "\$foo=: $foo\n";

	rename "/var/log/stingerd.log" , $foo;
	system ("/usr/bin/gzip " . $foo);
	unlink $foo; # a safety thing
      }

  } ## close  sub mv_old_log

sub become_daemonic
  {

# /usr/local/bin/perl -w -d does not catch this code with debugger and complain!
# bother it as little as possible!

# by Zaxo (see perlmonks.org)
# based on W. Richard Stevens' rules; see Advanced Programming in the UNIX Environment

my $debug = 1;
my $logfile = q(.testlog);

# Season to taste
my @fh_unused = (\*STDIN, \*STDOUT);

open \*STDERR, ">> $ENV{'HOME'}/$logfile";
select((select(\*STDERR), $| = 1)[0]);

{
# Daemon Rule 1) Fork and exit the parent.
     $ppid = $$;          # Another way to get at PID
     sleep 1;
     $pid = fork and exit 0;  
    ! defined $pid and die "No Fork: ", $!;
    while (kill 0, $ppid) {
        select undef, undef, undef, .001;
    };
}

# Daemon Rule 2) become session leader, pg leader, no term
my $session_id = POSIX::setsid();

# Daemon Rule 3) cd to /
chdir '/' or die "Could not cd to rootfs", $!;

# Daemon Rule 4) set file creation mask to 0
my $oldmask = umask 00;

# Daemon Rule 5) Close unneeded file handles
close $_ or die $! for @fh_unused;

  }# close subroutine



-- 
__________________________________________________________
Sign-up for your own personalized E-mail at Mail.com
http://www.mail.com/?sr=signup

CareerBuilder.com has over 400,000 jobs. Be smarter about your job search
http://corp.mail.com/careers