⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psa-chapter08.txt

📁 perl语言的经典文章
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Example code from Perl for System Administration by David N. Blank-Edelman
O'Reilly and Associates, 1st Edition, ISBN 1-56592-609-9

Chapter Eight
=============

#*
#* sending mail using sendmail (from the Perl FAQ)
#*

# assumes we have sendmail installed
open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq") or 
  die "Can't fork for sendmail: $!\n";
print SENDMAIL <<"EOF";
From: User Originating Mail <me\@host>
To: Final Destination <you\@otherhost>
Subject: A relevant subject line

Body of the message goes here after the blank line
in as many lines as you like.
EOF
close(SENDMAIL) or warn "sendmail didn't close nicely"; 
-------
#*
#* sending mail using AppleScript from MacPerl
#*

$to="someone\@example.com";
$from="me\@example.com";
$subject="Hi there";
$body="message body\n";

MacPerl::DoAppleScript(<<EOC);
tell application "Eudora"

    make message at end of mailbox "out"
       
    -- 0 is the current message
    set field \"from\" of message 0 to \"$from\"
    set field \"to\" of message 0 to \"$to\"
    set field \"subject\" of message 0 to \"$subject\"
    set body of message 0 to \"$body\"
    queue message 0
    connect with sending without checking
    quit
end tell
EOC
-------
#*
#* send mail using Apple Events from MacPerl
#*

use Mac::Glue ':glue';

$e=new Mac::Glue 'Eudora';
$to="someone\@example.com";
$from="me\@example.com";
$subject="Hi there";
$body="message body";

$e->make(
	new => 'message',
	at => location(end => $e->obj(mailbox => 'Out'))
);

$e->set($e->obj(field => from    => message => 0), to => $from);
$e->set($e->obj(field => to      => message => 0), to => $to);
$e->set($e->obj(field => subject => message => 0), to => $subject);
$e->set($e->prop(body => message => 0), to => $body);

$e->queue($e->obj(message => 0));
$e->connect(sending => 1, checking => 0);
$e->quit;
-------
#*
#* send mail using MAPI (via OLE) with Outlook on NT/2000
#*

$to="me\@example.com";
$subject="Hi there";
$body="message body\n";

use Win32::OLE;

# init OLE, COINIT_OLEINITIALIZE required when using MAPI.Session objects
Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# create a session object that will call Logoff when it is destroyed
my $session = Win32::OLE->new('MAPI.Session','Logoff');
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# log into that session using the default OL98 Internet Profile
$session->Logon('Microsoft Outlook Internet Settings');
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# create a message object
my $message = $session->Outbox->Messages->Add;
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# create a recipient object for that message object
my $recipient = $message->Recipients->Add;
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# populate the recipient object
$recipient->{Name} = $to;
$recipient->{Type} = 1; # 1 = "To:", 2 = "Cc:", 3 = "Bcc:"

# all addresses have to be resolved against a directory 
# (in this case probably your Address book). Full addresses 
# usually resolve to themselves, so this line in most cases will 
# not modify the recipient object.
$recipient->Resolve();
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# populate the Subject: line and message body
$message->{Subject} = $subject;
$message->{Text} = $body;

# queue the message to be sent
# 1st argument = save copy of message
# 2nd argument = allows user to change message w/dialog box before sent
# 3rd argument = parent window of dialog if 2nd argument is True
$message->Send(0, 0, 0);
die Win32::OLE->LastError(),"\n" if Win32::OLE->LastError();

# explicitly destroy the $session object, calling $session->Logoff 
# in the process
undef $session; 
-------
#*
#* sending mail using Mail::Mailer
#*

use Mail::Mailer;

$from="me\@example.com";
$to="you\@example.com";
$subject="Hi there";
$body="message body\n";

$type="smtp";
$server="mail.example.com";

my $mailer = Mail::Mailer->new($type, Server => $server) or
  die "Unable to create new mailer object:$!\n";

$mailer->open({From => $from, 
               To => $to, 
               Subject => $subject}) or 
  die "Unable to populate mailer object:$!\n";

print $mailer $body;
$mailer->close;
-------
#*
#* subroutine for performing exponential backoff (uses a closure)
#*

$max  = 24*60*60; # maximum amount of delay in seconds (1 day)
$unit = 60;       # increase delay by measures of this unit (1 min)

# provide a closure with the time we last sent a message and 
# the last power of 2 we used to compute the delay interval. 
# The subroutine we create will return a reference to an 
# anonymous array with this information
sub time_closure {
    my($stored_sent,$stored_power)=(0,-1);
    return sub {
       (($stored_sent,$stored_power) = @_) if @_;
       [$stored_sent,$stored_power];
    }
};

$last_data=&time_closure; # create our closure

# return true first time called and then once after an 
# exponential delay
sub expbackoff {
    my($last_sent,$last_power) = @{&$last_data};

    # reply true if this is the first time we've been asked, or if the
    # current delay has elapsed since we last asked. If we return true, 
    # we stash away the time of our last affirmative reply and increase 
    # the power of 2 used to compute the delay.
    if (!$last_sent or
       ($last_sent + 
         (($unit * 2**$last_power >= $max) ? 
             $max : $unit * 2**$last_power) <= time())){
         	       &$last_data(time(),++$last_power);
              return 1;
    }
    else {
	   return 0;
    }
}
-------
#*
#* subroutine for performing exponential ramp up (uses a closure)
#*

$max  = 60*60*24; # maximum amount of delay in seconds (1 day)
$min  = 60*5;     # minimum amount of delay in seconds (5 minutes)
$unit = 60;       # decrease delay by measures of this unit (1 min)

$start_power = int log($max/$unit)/log(2); # find the closest power of 2 

sub time_closure {
    my($last_sent,$last_power)=(0,$start_power+1);
    return sub {
	(($last_sent,$last_power) = @_) if @_;
	# keep exponent positive
	$last_power = ($last_power > 0) ? $last_power : 0; 
	[$last_sent,$last_power];
    }
};

$last_data=&time_closure; # create our closure

# return true first time called and then once after an 
# exponential ramp up
sub exprampup {
    my($last_sent,$last_power) = @{&$last_data};

    # reply true if this is the first time we've been asked, or if the
    # current delay has elapsed since we last asked. If we send, we
    # stash away the time of our last affirmative reply and increased
    # power of 2 used to compute the delay.
    if (!$last_sent or
	($last_sent + 
         (($unit * 2**$last_power <= $min) ? 
	  $min : $unit * 2**$last_power) <= time())){
	    &$last_data(time(),--$last_power);
            return 1;
    }
    else {
	return 0;
    }
}
-------
#*
#* a program that collates the responses of several machines and sends out
#* a summary piece of email
#*

use Mail::Mailer;
use Text::Wrap;

# the list of machine reporting in
$repolist = "/project/machinelist"; 
# the directory where they write files
$repodir  = "/project/reportddir";  
# filesystem separator for portability, 
# could use File::Spec module instead 
$separator= "/";                    
# send mail "from" this address
$reportfromaddr  = "project\@example.com"; 
# send mail to this address
$reporttoaddr    = "project\@example.com"; 
# read the list of machine reporting in into a hash. 
# Later we de-populate this hash as each machine reports in, 
# leaving behind only the machine which are missing in action
open(LIST,$repolist) or die "Unable to open list $repolist:$!\n";
while(<LIST>){
    chomp;
    $missing{$_}=1;
    $machines++;
}

# read all of the files in the central report directory
# note:this directory should be cleaned out automatically 
# by another script
opendir(REPO,$repodir) or die "Unable to open dir $repodir:$!\n";

while(defined($statfile=readdir(REPO))){
    next unless -f $repodir.$separator.$statfile;
    
    # open each status file and read in the one-line status report
    open(STAT,$repodir.$separator.$statfile) 
      or die "Unable to open $statfile:$!\n";

    chomp($report = <STAT>);

    ($hostname,$result,$details)=split(' ',$report,3);

    warn "$statfile said it was generated by $hostname!\n"
      if($hostname ne $statfile);

    # hostname is no longer considered missing
    delete $missing{$hostname}; 
    # populate these hashes based on success or failure reported
    if ($result eq "success"){
        $success{$hostname}=$details;
        $succeeded++;
    }
    else {
        $fail{$hostname}=$details;
        $failed++;
    }	
    close(STAT);
}		
closedir(REPO);

# construct a useful subject for our mail message
if ($successes == $machines){
    $subject = "[report] Success: $machines";
}
elsif ($failed == $machines or scalar keys %missing >= $machines) {
    $subject = "[report] Fail: $machines";
}
else {
    $subject = "[report] Partial: $succeeded ACK, $failed NACK".
      ((%missing) ? ", ".scalar keys %missing." MIA" : "");
}

# create the mailer object and populate the headers
$type="sendmail"; 
my $mailer = Mail::Mailer->new($type) or
  die "Unable to create new mailer object:$!\n";

$mailer->open({From=>$reportfromaddr, To=>$reporttoaddr, Subject=>$subject}) or 
  die "Unable to populate mailer object:$!\n";

# create the body of the message
print $mailer "Run report from $0 on " . scalar localtime(time) . "\n";

if (keys %success){
    print $mailer "\n==Succeeded==\n";
    foreach $hostname (sort keys %success){
	print $mailer "$hostname: $success{$hostname}\n";
    }
}

if (keys %fail){
    print $mailer "\n==Failed==\n";
    foreach $hostname (sort keys %fail){
	print $mailer "$hostname: $fail{$hostname}\n";
    }
}

if (keys %missing){
    print $mailer "\n==Missing==\n";
    print $mailer wrap("","",join(" ",sort keys %missing)),"\n";
}

# send the message
$mailer->close;
-------
#*
#* a simple network logging daemon that collates responses
#*

use IO::Socket;
use Text::Wrap; # used to make the output prettier

# the list of machine reporting in
$repolist = "/project/machinelist"; 
# the port number clients should connect to 
$serverport = "9967";               

&loadmachines; # load the machine list

# set up our side of the socket
$reserver = IO::Socket::INET->new(LocalPort => $serverport,
                                  Proto     => "tcp",
                                  Type      => SOCK_STREAM,
                                  Listen    => 5,
                                  Reuse     => 1)
  or die "Unable to build our socket half: $!\n";

# start listening on it for connects
while(($connectsock,$connectaddr) = $reserver->accept()){

    # the name of the client which has connected to us
    $connectname = gethostbyaddr((sockaddr_in($connectaddr))[1],AF_INET);

    chomp($report=$connectsock->getline);

    ($hostname,$result,$details)=split(' ',$report,3);

    # if we've been told to dump our info, print out a ready-to-go mail
    # message and reinitialize all of our hashes/counters
    if ($hostname eq "DUMPNOW"){
	&printmail($connectsock);
	close($connectsock);
	undef %success;
	undef %fail;
	$succeeded = $failed = 0;
	&loadmachines;
	next;
    }

    warn "$connectname said it was generated by $hostname!\n"
      if($hostname ne $connectname);
    delete $missing{$hostname};
    if ($result eq "success"){
	$success{$hostname}=$details;
	$succeeded++;
    }
    else {
	$fail{$hostname}=$details;
	$failed++;
    }	
    close($connectsock);
}
close($reserver);

# loads the list of machines from the given file
sub loadmachines {
    undef %missing;
    undef $machines; 
    open(LIST,$repolist) or die "Unable to open list $repolist:$!\n";
    while(<LIST>){
	chomp;
	$missing{$_}=1;
	$machines++;
    }
}

# prints a ready to go mail message. The first line is the subject, 
# subsequent lines are all the body of the message
sub printmail{
    ($socket) = $_[0];

    if ($successes == $machines){
	$subject = "[report] Success: $machines";
    }
    elsif ($failed == $machines or scalar keys %missing >= $machines) {
	$subject = "[report] Fail: $machines";
    }
    else {
	$subject = "[report] Partial: $succeeded ACK, $failed NACK".
	  ((%missing) ? ", ".scalar keys %missing." MIA" : "");
    }

    print $socket "$subject\n";
    
    print $socket "Run report from $0 on ".scalar localtime(time)."\n";

    if (keys %success){
	print $socket "\n==Succeeded==\n";
	foreach $hostname (sort keys %success){
	    print $socket "$hostname: $success{$hostname}\n";
	}
    }

    if (keys %fail){
	print $socket "\n==Failed==\n";
	foreach $hostname (sort keys %fail){
	    print $socket "$hostname: $fail{$hostname}\n";
	}
    }

    if (keys %missing){
	print $socket "\n==Missing==\n";
	print $socket wrap("","",join(" ",sort keys %missing)),"\n";
    }
}
-------
#*
#* a sample client for the above daemon
#*

use IO::Socket;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -