Sophie

Sophie

distrib > Mageia > 1 > i586 > by-pkgid > 00b61514f011a398c667f4cb5cd2e8fa > files > 195

heartbeat-2.1.4-3.mga1.i586.rpm

<!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
  <meta http-equiv="Content-Type"
 content="text/html; charset=iso-8859-1">
  <meta name="GENERATOR"
 content="Mozilla/4.7 [en] (Win98; U) [Netscape]">
</head>
<body>
<b><font size="+2"><font color="#000000">Synchronizing</font> Disks for
HA</font></b>
<p><b><font size="+1">What is this document?</font></b> <br>
<i>This is only ONE way to keeps nodes in synchronization for a high
availability cluster.&nbsp; It suits our needs and may be a good</i> <br>
<i>starting block for others so I'm sharing it.&nbsp; Your mileage may
vary.</i> </p>
<p><i>We used this on a web server to update ~1GB worth of documents in
sync every 10 minutes.&nbsp; Depending on how quickly your files change,
you may be able to update more data, more frequently.&nbsp; I would not
recommend using this without a private fast ethernet channel, i.e. an
extra NIC in each node connected via a crossover cable.<br>
</i></p>
<p><i>To determine whether this method would be appropriate for you,
you may wish to do this:</i> </p>
<ol>
  <li> <i>Set the minimum update rate you find acceptable (say, 3
minutes).</i></li>
  <li> <i>Conservatively approximate the amount of data you would
expect to change in 3 minutes (200MB)</i></li>
  <li> <i>Assuming you can count on 6MB/sec from your fast ethernet,
multiply this by 1/3 of your update time.&nbsp; Why?&nbsp; You need to
account for rsync (relatively slow executing) to determine what needs
updating and disk write time.&nbsp; In our example, this would give us
360MB worth of updates per cycle.</i></li>
</ol>
<i>Of course, you can always do what I did - set it up and see if it
updates fast enough.&nbsp; The scripts I've provided will notify you if
it kicks off again before the previous one <br>
finished.......</i>
<p><i>BTW, for lots of data, or rapidly changing data, you'll want a
shared disk or use <a
 href="http://www.complang.tuwien.ac.at/reisner/drbd/">drbd</a>.
&nbsp;However, we find rsync is still very useful to keep config files,
passwd files, etc. consistent and use it in conjuction with drbd.<br>
</i> </p>
<p><i><font color="#000000">One last item:&nbsp; rsync with the
--delete option is </font><font color="#ff0000">dangerous</font><font
 color="#000000">!&nbsp; Make sure your command options point to the
proper destination!&nbsp; Test this on non-critical data.&nbsp; And
then test it again.</font></i> <br>
&nbsp; </p>
<p><b><font size="+1">What you'll need:</font></b> </p>
<p>&nbsp;&nbsp;&nbsp; 1.&nbsp; OpenSSH <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
You can get it at:&nbsp; <a href="http://www.openssh.com/portable.html">http://www.openssh.com/portable.html</a><br>
&nbsp;&nbsp;&nbsp; 2.&nbsp; A copy of rsync <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Found at <a href="http://rsync.samba.org/ftp/rsync/binaries/">http://rsync.samba.org/ftp/rsync/binaries/</a>&nbsp;&nbsp;&nbsp;
-OR-&nbsp;&nbsp; <a
 href="http://rsync.samba.org/ftp/rsync/rsync-2.3.1.tar.gz">http://rsync.samba.org/ftp/rsync</a><br>
&nbsp;&nbsp; 3.&nbsp;&nbsp; Cron and stuff to mirror. </p>
<p>&nbsp;&nbsp;&nbsp; <i><font size="-1">In actuality, you don't even
need SSH.&nbsp; You could use rsh instead, <b><font color="#ff0000">if
your security needs permit it.</font></b></font></i> </p>
<p><b><font size="+1">Installing SSH</font></b> </p>
<p><font color="#ff6600">START HERE for source distribution:</font> <br>
Untar your openssh distribution.&nbsp; You might want to read the
INSTALL file or HOWTO, but most can get by with the following: <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b><tt>./configure</tt></b> <br>
<b><tt>&nbsp;&nbsp;&nbsp;&nbsp; make</tt></b> <br>
<b><tt>&nbsp;&nbsp;&nbsp;&nbsp; make install</tt></b> </p>
<p><font color="#ff6600">START HERE for rpm distribution after running
"rpm -ivh openssh_&lt;version#&gt;.rpm":</font> <br>
Once this is done, make sure sshd is started on bootup.&nbsp; This
could be done via init.d scripts or by placing (if ssh is installed to
the default location) "/usr/local/sbin/sshd" in you /etc/rc.d/rc.local
file.&nbsp; Type this in now to start it.<br>
<br>
<span style="color: rgb(255, 102, 0);"><span style="font-weight: bold;">NOTE:
&nbsp;&nbsp;&nbsp; &nbsp;YOU SHOULD READ THE OPENSSH DOCUMENTATION.
&nbsp;THE FOLLOWING INSTRUCTIONS WILL INSTRUCT YOU<br>
ON ONE WAY TO SET UP AUTO-AUTHENTICATION BETWEEN YOUR CLUSTER
NODES....BUT YOU SHOULD UNDERSTAND WHAT<br>
YOU ARE DOING!!!<br>
</span></span> </p>
<p>Make sure that /usr/local/bin is in your path and type:&nbsp;
"ssh-keygen -d"&nbsp;&nbsp;&nbsp; This will create your ssh
"key".&nbsp;&nbsp; Do not enter a passphrase (hit return). </p>
In your ~/.ssh directory, there will be two files: &nbsp;"id_dsa" and
"id_dsa.pub". &nbsp;"id_dsa" is your private key, "id_dsa.pub" is your
public key (please refer to your<br>
ssh documentation for explanations). &nbsp;Run the following commands:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold;">cp
id_dsa.pub authorized_keys2</span><br>
<span style="font-weight: bold;"></span></div>
<div style="margin-left: 40px;"><span style="font-weight: bold;">chmod
400 authorized_keys2</span><br>
</div>
Now copy the entire .ssh directory (preserving permissions) to your
home directory on the other node in the cluster. <br>
<br>
You should be all set.&nbsp; Try it out by typing on node A:&nbsp; "ssh
nodeB".&nbsp; You should be logged in to nodeB without having to type
anything (except "yes" to accept<br>
the host key the very first time you connect....)<br>
&nbsp;
<p><b><font size="+1">Installing Rsync</font></b> </p>
<p>Well, I'm not really going to tell you how to do this.&nbsp; I just
used the rpm.&nbsp; If that's not possible for you, I'm sure the good
folks at samba will have a nice README.Install for you to follow.&nbsp;
However, the binary link in the "What you'll need" section has binaries
for just about all flavors.&nbsp; Here's the link for the
rpm:&nbsp;&nbsp; <a
 href="http://rsync.samba.org/ftp/rsync/binaries/redhat">http://rsync.samba.org/ftp/rsync/binaries/redhat</a> </p>
<p><b><font size="+1">Determining your Rsync command</font></b> </p>
<p>For our example, let's say you have a web server cluster.&nbsp; As a
result, you need the directory tree "/html" to be current on both
nodes.&nbsp; Assuming node A is the master, I would use the command
from node A: </p>
<pre><i>&nbsp;&nbsp;&nbsp; <tt>rsync --rsh=/usr/local/bin/ssh -naurvl --delete /html/ localnetB:/html</tt></i></pre>
Let's note a few things.&nbsp; First, since this will be used with
cron, you want to be sure that you use the full path for the ssh
executable (and the rsync executable for that matter).&nbsp; Also, note
the "/html/" syntax.&nbsp; This last "/" is necessary - otherwise
you'll have the tree "/html/html" on your slave.&nbsp; Lastly, I used
the "-n" option.&nbsp; This is for a dry run.&nbsp; You want to do this
to make sure everything is copied/deleted as you would expect it.&nbsp;
When you put this in your crontab file, you'll leave off the "-n"
option.&nbsp; Similarly, the "-v" verbosity option is only for this
test.&nbsp; In your crontab entry, it will be replaced with the "-q"
option for quiet.&nbsp; Test the command now and make sure it does what
you want - the "--delete" option can be dangerous!
<p><b><font size="+1">Create your sync script and crontab entry</font></b> </p>
<p>You now want to create the script which will run rsync every X
minutes via cron.&nbsp; Our solution has the same script running on
both nodes, but it checks whether it is running on the current primary
(the one holding the services) or not. &nbsp;If it's running on the
secondary, it quits immediately. &nbsp;I use the following perl script,
called "synch_all.pl": </p>
<center>
<table border="1" bgcolor="#ffffcc" nosave="">
  <tbody>
    <tr nosave="">
      <td nosave=""><i><tt>#!/usr/bin/perl<br>
      <br>
      </tt></i>use strict;<br>
use diagnostics;<br>
      <br>
use lib "/root/scripts";<br>
use whohostlib;<br>
use EnvConfig;<br>
use Mail::Sendmail;<br>
      <br>
#Take care of two-way syncing case during shutdown of one server.
&nbsp;Skips the first try to sync after failover.<br>
if ( -e "/var/lock/subsys/mirrorstop" ) {<br>
&nbsp;&nbsp;&nbsp; unlink "/var/lock/subsys/mirrorstop";<br>
&nbsp;&nbsp;&nbsp; exit;<br>
}<br>
      <br>
# Only sync if serving IP<br>
my $dirname = "";<br>
my $filename = "";<br>
      <br>
#Get server that this is running on...<br>
my $me = "";<br>
my $other = "";<br>
($me,$other) = whohostlib::whohost;<br>
      <br>
if (&amp;whohostlib::whostatus() == 1)<br>
{<br>
&nbsp;&nbsp;&nbsp; #I'm serving! &nbsp;You want fries with that?<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; #Only sync if other node is running heartbeat:<br>
&nbsp;&nbsp;&nbsp; my $tst = `$EnvConfig::sshpath local$other
/etc/rc.d/init.d/heartbeat status`;<br>
&nbsp;&nbsp;&nbsp; # For 0.4.9.2 and earlier use &nbsp;---&gt; &nbsp;
&nbsp;if ($tst =~ /running.../) {<br>
&nbsp; &nbsp; # For 0.4.9 "beta" versions...<br>
&nbsp;&nbsp;&nbsp; if ($tst =~ /heartbeat OK/) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #make sure previous mirror has
completed...<br>
      <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #To avoid hard link probs over
partitions, created /var/lock/subsys/.DONOTREMOVE file<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if
(link("/var/lock/subsys/.DONOTREMOVE", "/var/lock/subsys/mirror")) { <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; # /home/
-&nbsp; Home Directories (all users)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #
/root/scripts/ - Root scripts/system scripts - like where we put this
script...<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #
/var/spool/cron/ - System crontabs<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; my @dirlist = ( "/home/", "/root/scripts/",
"/var/spool/cron/" );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; foreach $dirname (@dirlist) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; system "/usr/bin/rsync
--rsh=$EnvConfig::sshpath $EnvConfig::rsyncoptions $dirname
local$other:$dirname";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
      <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #
/etc/password - System Password File<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #
/etc/shadow&nbsp;&nbsp; - Actual Encrypted passwords.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #
/etc/group&nbsp;&nbsp;&nbsp; - System Group File<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #
/etc/ld.so.conf - System Linked Libraries.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #
/etc/shells&nbsp;&nbsp;&nbsp;&nbsp; - Valid Login Shells<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; my @filelist = ( "/etc/passwd", "/etc/shadow",
"/etc/group", "/etc/ld.so.conf", "/etc/shells" );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; foreach $filename (@filelist) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; system "/usr/bin/rsync
--rsh=$EnvConfig::sshpath $EnvConfig::rsyncoptions $filename
local$other:$filename";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; }<br>
      <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; # release
rsync process<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unlink
"/var/lock/subsys/mirror";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; my $ddd =
`date`;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; my $subject =
"Next RSYNC process starting before previous has completed!\n";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; my $message =
$subject.$ddd;<br>
      <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sendmail
('smtp' =&gt; $EnvConfig::smtphost,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 'To' =&gt; 'admin@domain.com,admin2@domain.com',<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 'From' =&gt; 'cluster@domain.com',<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 'Reply-To' =&gt; 'cluster@domain.com',<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 'Subject' =&gt; $subject,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; 'Message' =&gt; $message)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; or warn "Next
RSYNC process starting before previous has completed (Couldn't send
email)";<br>
      <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #Try to get to
known state by killing all synch procs and removing link...<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unlink
"/var/lock/subsys/mirror";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exec
"/root/scripts/kill_synchs.sh";<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #"kill_synchs.sh is a one
liner: &nbsp;ps ax | grep synch_all | awk {'print $1'} | xargs -n1 kill
-9<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
}<br>
      </td>
    </tr>
  </tbody>
</table>
</center>
<br clear="all">
Mail::Sendmail is a standard Perl module you can get from <a
 href="www.cpan.org">CPAN</a>, but you'll notice two homemade ones.
&nbsp;There's no magic here, just decided to use them for portability
and readability (yes, I know, even though it's perl ;-)). &nbsp;The
"EnvConfig" one lets us set the paths and options we're using external
to the script so that the<br>
actual synch_all.pl script doesn't change. &nbsp;You could even add the
file and directory lists to this, but ours doesn't change much cluster
to cluster. &nbsp;The "whohostlib" has two functions used often.
&nbsp;One checks which host the script is running on, and the other
(whostatus) checks whether the node running the script is holding the
services.<br>
<br>
<table border="1"
 style="background-color: rgb(255, 255, 204); text-align: left; margin-left: auto; margin-right: auto;"
 nosave="" cellpadding="5">
  <tbody>
    <tr>
      <td># Configuration file for all scripts, including host
definitions, etc.<br>
      <br>
package EnvConfig;<br>
      <br>
#www_host = "wwwdev.domain.com";<br>
$www_host = "wwwint.domain.com";<br>
#www_host = "wwwprod.domain.com";<br>
      <br>
$sshpath = "/usr/bin/ssh";<br>
      <br>
$rsyncoptions = "-aurlq --delete";<br>
#$rsyncoptions = "-aurlv";<br>
      <br>
$smtphost = 'mail.domain.com';<br>
      <br>
$Debug = 0;<br>
1;<br>
      </td>
    </tr>
  </tbody>
</table>
<br>
<br>
<br>
<table border="1"
 style="background-color: rgb(255, 255, 204); text-align: left; margin-left: auto; margin-right: auto;"
 nosave="" cellpadding="5">
  <tbody>
    <tr>
      <td>#!/usr/bin/perl<br>
      <br>
use strict;<br>
use diagnostics;<br>
      <br>
package whohostlib;<br>
sub whohost {<br>
&nbsp;&nbsp;&nbsp; my $other;<br>
&nbsp;&nbsp;&nbsp; my $me;<br>
      <br>
&nbsp;&nbsp;&nbsp; #Who am I?<br>
&nbsp;&nbsp;&nbsp; $me = `hostname -s`;<br>
&nbsp;&nbsp;&nbsp; chomp $me;<br>
&nbsp;&nbsp;&nbsp; $me =~ s/[a-zA-Z]//g;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; if ($me) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; $other = 0;<br>
&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; $other = 1;<br>
&nbsp;&nbsp;&nbsp; }<br>
      <br>
&nbsp;&nbsp;&nbsp; return($me,$other);<br>
}<br>
      <br>
#By doing "grep mirror haresources", we peel off the line with the info
we want...the cluster IP. &nbsp;Mirror will be added to you haresources
later...<br>
sub whostatus {<br>
&nbsp;&nbsp;&nbsp; my $status = 0;<br>
&nbsp;&nbsp;&nbsp; my $x = `grep mirror /etc/ha.d/haresources`;<br>
&nbsp;&nbsp;&nbsp; my @p = split(' ',$x);<br>
&nbsp;&nbsp;&nbsp; my $ip = $p[1];<br>
&nbsp;&nbsp;&nbsp; $ip =~ s/IPaddr:://g;<br>
&nbsp;&nbsp;&nbsp; $x = `/etc/ha.d/resource.d/IPaddr $ip
status`;&nbsp;&nbsp;&nbsp; <br>
      <br>
&nbsp;&nbsp;&nbsp; # If I am primary, return 1 else return 0<br>
&nbsp;&nbsp;&nbsp; if ($x =~ /running/) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; $status = 1;<br>
&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; $status = 0;<br>
&nbsp;&nbsp;&nbsp; }<br>
      <br>
&nbsp;&nbsp;&nbsp; return $status;<br>
}<br>
      <br>
      <br>
1; #Return True Value<br>
      </td>
    </tr>
  </tbody>
</table>
<br>
<br>
<b>NOTE: &nbsp;</b>We use a convention for our clusters that if the
clustername is "foo" the two nodes that make up the cluster will be
named "foo0" and "foo1". &nbsp;The private data interfaces are given
the hostnames "local0" and "local1". &nbsp;This makes stuff easier with
scripting, but you don't have to do it.<br>
<b><br>
</b><b>NOTE #2:</b>&nbsp; You may not want a mail fired off.&nbsp; You
may just want a log entry.&nbsp; You might want both.&nbsp; If you're
unfamiliar with perl, to add a log entry, substitute all the commands
with "MAIL" in them above with the following:
<center>
<table border="1" bgcolor="#ffffcc" nosave="">
  <tbody>
    <tr>
      <td><i><tt>open(LOG,"&gt;&gt;/var/log/ha-log");</tt></i> <br>
      <i><tt>$dstr = `date +%Y/%m/%d_%T`;</tt></i> <br>
      <i><tt>chomp $dstr;</tt></i> <br>
      <i><tt>print LOG "$dstr RSYNC: Process starting before previous
one completes!\n";</tt></i> <br>
      <i><tt>close LOG;</tt></i></td>
    </tr>
  </tbody>
</table>
</center>
<br>
At this point you want to create your crontab entry.&nbsp; The hard
link prevents more than one sync process from running at the same time,
but you want to have a decent idea of how often you need to synchronize
and how long it will take to synchronize.&nbsp;
<p>SO, once you determine how often you'll be synchronizing, type
"crontab -e" to modify your crontab entry.&nbsp; If you don't like vi,
try using "setenv EDITOR /usr/local/bin/emacs" (or export for bash
users) to select emacs or a different editor.&nbsp; If you want to
synchronize every 10 minutes, your entry would look like this: </p>
<blockquote>
  <pre><i>*/10 * * * * /script_directory/sync.pl &amp;&gt; /dev/null</i></pre>
</blockquote>
You could also redirect output to some logfile if you desire, but keep
in mind how often it runs.
<p><b><font size="+1">Dealing with Failover</font></b> </p>
<p>We're just about there now.&nbsp; The last thing you need to
consider is when you shutdown. &nbsp;You want to do one last
synchronization before you shut down. &nbsp;I accomplished this with a
heartbeat service called "mirror". &nbsp;On startup, we do nothing
other than prevent the very first synch_all (as a precaution) and
notify the necessary admins about the failover. </p>
<p><b>NOTE:</b>&nbsp;&nbsp; You will want to be sure that any
applications writing to the synch'ed areas stop before your last
sync.&nbsp; If these applications are controlled via the ipresources
configuration file, you can ensure this by listing the "mirror" script
right after your IP address. &nbsp;However, if they are not, you may
want to add an application exit to the beginning of your mirror script. </p>
<p><b></b></p>
<center>
<table border="1" bgcolor="#ffffcc" nosave="">
  <tbody>
    <tr nosave="">
      <td nosave="">#!/usr/bin/perl<br>
      <br>
use lib "/root/scripts";<br>
use whohostlib;<br>
      <br>
# See how we were called.<br>
if ($#ARGV == 0) {<br>
&nbsp;&nbsp;&nbsp; $switch = $ARGV[0];<br>
} else {<br>
&nbsp;&nbsp;&nbsp; print "Usage: mirror {start|stop|status|restart}\n";<br>
&nbsp;&nbsp;&nbsp; exit -1;<br>
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
      <br>
#&nbsp; start)<br>
      <br>
if ($switch eq "start") {<br>
&nbsp;&nbsp;&nbsp; #Make sure to skip first sync.....<br>
&nbsp;&nbsp;&nbsp; ($me,$other) = whohostlib::whohost;<br>
&nbsp;&nbsp;&nbsp; system ("/usr/bin/ssh local$me /bin/touch
/var/lock/subsys/mirrorstop");<br>
&nbsp;&nbsp;&nbsp; #Notify admins of startup....<br>
&nbsp;&nbsp;&nbsp; open (XXX,"/root/scripts/.pagelist");<br>
&nbsp;&nbsp;&nbsp; $hh = `hostname`;<br>
&nbsp;&nbsp;&nbsp; chomp $hh;<br>
&nbsp;&nbsp;&nbsp; while (&lt;XXX&gt;) {<br>
&nbsp;&nbsp;&nbsp; chomp;<br>
&nbsp;&nbsp;&nbsp; system "/root/scripts/pagescript.pl $_ \"Starting up
heartbeat services on node $hh\"";<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; close XXX;<br>
&nbsp;&nbsp;&nbsp; <br>
} elsif ($switch eq "stop") {<br>
&nbsp;&nbsp;&nbsp; #stop)<br>
      <br>
&nbsp;&nbsp;&nbsp; print "Mirror stop: \n";<br>
      <br>
&nbsp;&nbsp;&nbsp; #Am I serving???<br>
&nbsp;&nbsp;&nbsp; #We'll consider mirror to be "running" if the IP is
on this box...<br>
&nbsp;&nbsp;&nbsp; $x = `grep mirror /etc/ha.d/haresources`;<br>
&nbsp;&nbsp;&nbsp; @p = split(' ',$x);<br>
&nbsp;&nbsp;&nbsp; $ip = $p[1];<br>
&nbsp;&nbsp;&nbsp; $x = `/etc/ha.d/resource.d/IPaddr $ip
status`;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; if ($x =~ /running/) {<br>
&nbsp;&nbsp;&nbsp; #Notify admins of shutdown....<br>
&nbsp;&nbsp;&nbsp; open (XXX,"/root/scripts/.pagelist");<br>
&nbsp;&nbsp;&nbsp; $hh = `hostname`;<br>
&nbsp;&nbsp;&nbsp; chomp $hh;<br>
&nbsp;&nbsp;&nbsp; while (&lt;XXX&gt;) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chomp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; system
"/root/scripts/pagescript.pl $_ \"Shutting down heartbeat services on
node $hh\"";<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; close XXX;<br>
      <br>
&nbsp;&nbsp;&nbsp; #You want fries with that?&nbsp; One last sync to
other box, if not in the middle of one now...<br>
&nbsp;&nbsp;&nbsp; if ( -e "/var/lock/subsys/mirror" ) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; print "Not syncing, already doing
so...\n";<br>
&nbsp;&nbsp;&nbsp; } else {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; print "Synchronizing data on
standby node: \n";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; system
"/root/scripts/synch_all.pl";<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; # To prevent NEW master from syncing back to us too
soon, lock their first synch_all...<br>
&nbsp;&nbsp;&nbsp; ($me,$other) = whohostlib::whohost;<br>
&nbsp;&nbsp;&nbsp; system ("/usr/bin/ssh local$other /bin/touch
/var/lock/subsys/mirrorstop");<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; <br>
} elsif ($switch eq "status") {<br>
&nbsp;&nbsp;&nbsp; #status)<br>
&nbsp;&nbsp;&nbsp; #We'll consider mirror to be "running" if the IP is
on this box...<br>
&nbsp;&nbsp;&nbsp; $y = `grep mirror /etc/ha.d/haresources`;<br>
&nbsp;&nbsp;&nbsp; @p = split(' ',$y);<br>
&nbsp;&nbsp;&nbsp; $ip = $p[1];<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; $x = `/etc/ha.d/resource.d/IPaddr $ip
status`;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; print $x;<br>
} elsif ($switch eq "restart") {<br>
&nbsp;&nbsp;&nbsp; #restart)<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; system "/etc/ha.d/resource.d/mirror stop";<br>
&nbsp;&nbsp;&nbsp; system "/etc/ha.d/resource.d/mirror start";<br>
&nbsp;&nbsp;&nbsp; <br>
} else {<br>
&nbsp;&nbsp;&nbsp; print "Usage: mirror {start|stop|status|restart}\n";<br>
}<br>
exit;<br>
      </td>
    </tr>
  </tbody>
</table>
</center>
<center></center>
<br>
Finally, you need to install the script in your ipresources on both
nodes.&nbsp; You'll want mirror to be the first service listed (after
IP).&nbsp; For our webserver, it would read:
<pre><i>&nbsp;&nbsp;&nbsp; nodeA 192.168.85.1 mirror httpd</i></pre>
&nbsp;
<p><b><font color="#ff0000"><font size="+3">Be Careful</font></font></b> </p>
<p>Please test your setup on non-critical data first.&nbsp; There could
be a bad typo above or whatever.&nbsp; The "--delete" option can be
dangerous.&nbsp; You've been warned. <br>
&nbsp; </p>
<p>Rev 1.0.0<br>
Rudy Pawul <br>
rpawul@iso-ne.com </p>
</body>
</html>