Tuesday, September 27, 2011

Perl One-liner

collection of one-liners.

# run contents of "my_file" as a program
perl my_file

# run debugger "stand-alone"
perl -d -e 42

# run program, but with warnings
perl -w my_file

# run program under debugger
perl -d my_file

# just check syntax, with warnings
perl -wc my_file

# useful at end of "find foo -print"
perl -nle unlink

# simplest one-liner program
perl -e 'print "hello world!\n"'

# add first and penultimate columns
perl -lane 'print $F[0] + $F[-2]'

# just lines 15 to 17
perl -ne 'print if 15 .. 17' *.pod

# print lines beween START and END in foo.txt to STDOUT
perl -ne 'print if /^START$/ .. /^END$/' foo.txt

# change all words "foo"s to "bar"s in every .c file and keep backups
perl -p -i.bak -e 's/\bfoo\b/bar/g' *.c

# substitute "xyz.math" to "abc.math" in every .html file and keep backups
perl -p -i.bak -e 's/xyz\.math/abc\.math/g' *.html

# insert department name after each title and keep backup
perl -p -i.bak -e 's##<title>Harvard .: #i' *.html<br /><br /> # change isolated occurrence of aaa to bbb in each file *.c or *.h<br /> perl -p -i.bak -e 's{\baaa\b}{bbb}g' *.[ch]<br /><br /> # command-line that prints the first 50 lines (cheaply) <br /> perl -pe 'exit if $. > 50' f1 f2 f3 ...<br /><br /> # a second way to print lines 3 to 5 of file foo.txt<br /> perl -pe 'exit if 3<$. && $.<5' foo.txt<br /><br /> # increments all numbers in foo.tx by 1<br /> perl -pe 's/(\d+)/ 1 + $1 /ge' foo.txt<br /><br /> # delete first 10 lines <br /> perl -i.old -ne 'print unless 1 .. 10' foo.txt<br /><br /> # change all the isolated oldvar occurrences to newvar <br /> perl -i.old -pe 's{\boldvar\b}{newvar}g' *.[chy]<br /><br /> # command-line that reverses the whole file by lines <br /> perl -e 'print reverse <>' file1 file2 file3 ....<br /><br /> # find palindromes <br /> perl -lne 'print if $_ eq reverse' /usr/dict/words<br /><br /> # find palindromes in a dictionary /usr/share/dict/words<br /> perl -lne 'print if $_ eq reverse' /usr/share/dict/words<br /><br /> # command-line that reverse all the bytes in a file <br /> perl -0777e 'print scalar reverse <>' f1 f2 f3 ...<br /><br /> # command-line that reverses the whole file by paragraphs <br /> perl -00 -e 'print reverse <>' file1 file2 file3 ....<br /><br /> # increment all numbers found in these files <br /> perl i.tiny -pe 's/(\d+)/ 1 + $1 /ge' file1 file2 ....<br /><br /> # command-line that shows each line with its characters backwards <br /> perl -nle 'print scalar reverse $_' file1 file2 file3 ....<br /><br /> # reverses order of characters in each line of foo.txt<br /> perl -nle 'print scalar reverse $_' foo.txt<br /><br /> # delete all but lines beween START and END <br /> perl -i.old -ne 'print unless /^START$/ .. /^END$/' foo.txt<br /><br /> # delete lines beween START and END and backup original file <br /> perl -i.old -ne 'print unless /^START$/ .. /^END$/' foo.txt<br /><br /> # binary edit (careful!) <br /> perl -i.bak -pe 's/Mozilla/Slopoke/g' /usr/local/bin/netscape<br /><br /> # delete first 10 lines in foo.txt and keep backup foo.txt.bak<br /> perl -i.bak -ne 'print unless 1 .. 10' foo.txt<br /><br /> # look for dup words <br /> perl -0777 -ne 'print "$.: doubled $_\n" while /\b(\w+)\b\s+\b\1\b/gi'<br /><br /> # command-line that prints the last 50 lines (expensively) <br /> perl -e 'lines = <>; print @@lines[ $#lines .. $#lines-50' f1 f2 f3 ... <br /><br /> # the always present hallo world program, adapted to a Math department<br /> perl -e 'print "Hello Mr Euler!\n"'<br /><br /> # rename in each file name the string aaa by bbb<br /> ls | perl -ne 'chomp; next unless -e; $o = $_; s/aaa/bbb/; next if -e; rename $o, $_'; <br /><br /> # add first and last column in each line of file foo.txt and print it out<br /> perl -lane 'print $F[0] + $F[-1]' foo.txt<br /><br /> # print lines 15 to 17 of file foo.txt<br /> perl -ne 'print if 15 .. 17' foo.txt<br /><br /> # the same but without backup. Remember the flags: "eat the pie"<br /> perl -p -i -e 's/foo/bar/g' *.c<br /><br /> # changes ^M newline characters to newlines <br /> perl -p -i -e 's/\012?\015/\n/g' $1<br /><br /> # the same but with all files with name filename<br /> perl -p -i -e 's/foo/bar' `find . -name "filename"`<br /><br /> # substitution can also be applied to binary files like test.ppm<br /> perl -p -i -e 's/255/127/g' test.ppm<br /><br /> # reverses lines of file foo.txt and print it<br /> perl -e 'print reverse <>' foo.txt<br /><br /> # reverses paragraphs in file foo.txt<br /> perl -00 -e 'print reverse <>' foo.txt<br /><br /> # look for duplicated words in a line<br /> perl -0777 -ne 'print "$.: doubled $_\n" while /\b(\w+)\b\s+\b\1\b/gi' foo.txt <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://www.blogger.com/profile/08055786710159541445' itemprop='url'/> <a class='g-profile' href='https://www.blogger.com/profile/08055786710159541445' rel='author' title='author profile'> <span itemprop='name'>virendersharma</span> </a> </span> </span> <span class='post-timestamp'> at <meta content='http://virendersharma.blogspot.com/2011/09/perl-one-liner.html' itemprop='url'/> <a class='timestamp-link' href='https://virendersharma.blogspot.com/2011/09/perl-one-liner.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2011-09-27T01:53:00-07:00'>1:53 AM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://virendersharma.blogspot.com/2011/09/perl-one-liner.html#comment-form' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-463720878'> <a href='https://www.blogger.com/post-edit.g?blogID=7460292314936920729&postID=3857803255243426910&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='7460292314936920729' itemprop='blogId'/> <meta content='4554536616839750317' itemprop='postId'/> <a name='4554536616839750317'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://virendersharma.blogspot.com/2011/09/configuring-odbc-with-php-oracle.html'>configuring odbc with php & oracle.</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-4554536616839750317' itemprop='description articleBody'> There are some steps for configuring odbc with php & oracle.<br /><br />Req: HTTPD, PHP, Oracle should be installed and functioned properly.<br /><br />Step 1. Install rpm package of unixODBC, which is available in rhel dvd.<br /><br />step 2. $ odbcinst -j <br /><br /> unixODBC 2.2.7<br /> DRIVERS............: /etc/odbcinst.ini<br /> SYSTEM DATA SOURCES: /etc/odbc.ini<br /> USER DATA SOURCES..: /home/auser/.odbc.ini<br /><br />step 3. For Oracle you need to copy all the libs to /usr/lib<br /><br /> cp /usr/lib/oracle/11.1/client/lib /usr/lib/<br /><br />step 4. /etc/odbcinst.ini Contents:<br /><br /> [Oracle]<br /> Description = Oracle ODBC Connection<br /> Driver = /usr/lib/oracle/11.1/client/lib/libsqora.so.11.1<br /> Setup =<br /> FileUsage =<br /> CPTimeout =<br /> CPReuse =<br /><br /> [Sybase]<br /> Description = Sybase ODBC Driver<br /> Driver = /opt/sybase/DataAccess/ODBC/lib/libsybdrvodb.so<br /> FileUsage = -1<br /><br />step 5. /etc/odbcinst.ini Contents:<br /><br /> [Oracle]<br /> Description = Oracle ODBC Connection<br /> Driver = /usr/lib/oracle/11.1/client/lib/libsqora.so.11.1<br /> Setup =<br /> FileUsage =<br /> CPTimeout =<br /> CPReuse =<br /><br /> [Sybase]<br /> Description = Sybase ODBC Driver<br /> Driver = /opt/sybase/DataAccess/ODBC/lib/libsybdrvodb.so<br /> FileUsage = -1<br /><br />Step 6. Testing DSN connections<br /> bash-2.05$ isql -v my_dsn username password<br /> +---------------------------------------+<br /> | Connected! |<br /> | |<br /> | sql-statement |<br /> | help [tablename] |<br /> | quit |<br /> | |<br /> +---------------------------------------+<br /> SQL><br /><br />Step 7. PHP Script to Test ODBC Connectivity:<br /><br /> <!--php<br /--><br /> $query = “select * from table_name”;<br /><br /> $conn = odbc_pconnect(“DSN”, “username”, “password”);<br /><br /> if(!$conn) die(“Connection failed”);<br /><br /> if($result = odbc_exec($conn, $query)) {<br /><br /> echo “Query returned : ” . odbc_num_rows($result) . “rows”;<br /><br /> odbc_result_all($result);<br /><br /> }<br /><br /> ?> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://www.blogger.com/profile/08055786710159541445' itemprop='url'/> <a class='g-profile' href='https://www.blogger.com/profile/08055786710159541445' rel='author' title='author profile'> <span itemprop='name'>virendersharma</span> </a> </span> </span> <span class='post-timestamp'> at <meta content='http://virendersharma.blogspot.com/2011/09/configuring-odbc-with-php-oracle.html' itemprop='url'/> <a class='timestamp-link' href='https://virendersharma.blogspot.com/2011/09/configuring-odbc-with-php-oracle.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2011-09-27T01:35:00-07:00'>1:35 AM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://virendersharma.blogspot.com/2011/09/configuring-odbc-with-php-oracle.html#comment-form' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-463720878'> <a href='https://www.blogger.com/post-edit.g?blogID=7460292314936920729&postID=4554536616839750317&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> </div></div> <div class="date-outer"> <h2 class='date-header'><span>Thursday, April 16, 2009</span></h2> <div class="date-posts"> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='7460292314936920729' itemprop='blogId'/> <meta content='3907177839402561847' itemprop='postId'/> <a name='3907177839402561847'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://virendersharma.blogspot.com/2009/04/globus-toolkit-408-grid-with-weka4ws.html'>Globus Toolkit 4.0.8 (GRID) with Weka4ws</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-3907177839402561847' itemprop='description articleBody'> Table of Contents (Globus Toolkit) -- INCOMPLETE<br /><br />1. Introduction<br />2. Setting up the first machine<br /><br />2.1. Pre-requisites<br />2.2. Building the Toolkit<br />2.3. Setting up security on your first machine<br />2.4. Set up GridFTP<br />2.5. Starting the webservices container<br />2.6. Configuring RFT<br />2.7. Setting up WS GRAM<br /><br />3. Setting up your second machine<br /><br />3.1. Setting up your second machine: Prereqs<br />3.2. Setting up your second machine: Installation<br />3.3. Setting up your second machine: Security<br />3.4. Setting up your second machine: GridFTP<br />3.5. Setting up your second machine: Webservices<br />3.6. Setting up your second machine: WS GRAM<br /><br />4. VO-level services<br /><br />4.1. Setting up an Index Service hierarchy<br />4.2. Configuring WebMDS<br />4.3. Creating a MyProxy server<br /><br />5. Setting up your cluster<br /><br />5.1. Cluster: prereqs<br />5.2. Cluster: install<br />5.3. Security on the cluster<br />5.4. GridFTP on the cluster<br />5.5. Cluster: Container<br />5.6. Cluster: RFT<br />5.7. Cluster: GRAM<br />5.8. Cluster: MDS<br /><br />6. Establishing Cross-CA Trust<br />7. Now what?<br /><br />1. Introduction<br /><br />This is a quickstart that shows a full installation of the Toolkit on two Centos 5 machines. It shows the installation of prereqs, installation of the toolkit, creation of certificates, and configuration of services. It is designed to supplement the main admin guide.<br /><br />The installer used throughout this document is the GT4.0.8 installer. There are no changes required to use this document with later 4.0.8 installers. You should use the most current version available.<br />2. Setting up the first machine<br />2.1. Pre-requisites<br /><br />I will be installing all of the toolkit from source, so I'm going to double-check my system for pre-requisites. The full list of prereqs is available at Software Prerequisites in the Admin Guide.<br /><br />First I'll check for zlib development libraries for GSI-OpenSSH:<br /><br />choate % yum install zlib zlib-devel gcc gcc-c++ tar sed make perl sudo postgresql postgresql-server postgresql-odbc xinetd<br /><br />Next, I'll install java from Sun, you can download from here.<br /><br />root@choate:~# cd /opt<br />root@choate:~# ./jdk-6u13-linux-i586.bin<br />root@choate:~# mv jdk1.6.0_13 java<br /><br />Next, we download from here, install ant:<br /><br />root@choate:~# cd /opt<br />root@choate:~# tar xzf apache-ant-1.7.1-bin.tar.gz<br />root@choate:~# mv apache-ant-1.7.1 ant<br />Aslo need to set JAVA_HOME and ANT_HOME<br />Add below entry in /etc/profile<br />export JAVA_HOME=/opt/java<br />export ANT_HOME=/opt/ant<br />export GLOBUS_LOCATION=/usr/local/globus-4.0.1<br />export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$GLOBUS_LOCATION/bin:$GLOBUS_LOCATION/sbin:$PATH<br /><br />2.2. Building the Toolkit<br /><br />That completes the list of build prereqs, so now I will download the installer from here and build it. The long version of these instructions is at Installing in the Admin Guide.<br /><br />root@cognito:~# useradd globus<br />root@choate:/etc/init.d# mkdir /usr/local/globus-4.0.1/<br />root@choate:/etc/init.d# chown globus:globus /usr/local/globus-4.0.1/<br /><br />Now, as the newly created globus user:<br /><br />root@cognito:~# su - globus<br />globus@choate:~$ tar xzf gt4.0.8-all-source-installer.tar.gz<br />globus@choate:~$ cd gt4.0.8-all-source-installer<br />globus@choate:~/gt4.0.8-all-source-installer$ ./configure --prefix=/usr/local/globus-4.0.1/ \<br /> --with-iodbc=/usr/lib<br />checking build system type... i686-pc-linux-gnu<br />checking for javac... /usr/java/j2sdk1.4.2_10//bin/javac<br />checking for ant... /usr/local/apache-ant-1.6.5/bin/ant<br />configure: creating ./config.status<br />config.status: creating Makefile<br /><br />Much better!<br /><br /> [Note]<br /> <br /><br /> Note<br /> <br /> <br /><br /> The machine I am installing on doesn't have access to a scheduler. If it did, I would have specified one of the wsgram scheduler options, like --enable-wsgram-condor, --enable-wsgram-lsf, or --enable-wsgram-pbs.<br /><br /><br /><br />Now it's time to build the toolkit:<br /><br />globus@choate:~/gt4.0.1-all-source-installer$ make | tee installer.log<br />cd gpt-3.2autotools2004 && OBJECT_MODE=32 ./build_gpt<br />build_gpt ====> installing GPT into /usr/local/globus-4.0.1/<br />...<br />Time for a coffee break here, the build will take over an hour, possibly<br />longer depending on how fast your machine is<br />...<br />echo "Your build completed successfully. Please run make install."<br />Your build completed successfully. Please run make install.<br />globus@choate:~/gt4.0.1-all-source-installer$ make install<br />/usr/local/globus-4.0.1//sbin/gpt-postinstall<br />...<br />..Done<br />globus@choate:~/gt4.0.1-all-source-installer$<br /><br />2.3. Setting up security on your first machine<br /><br />Now that the toolkit is installed, we're going to want hostcerts for the machine, and a usercert for me. To do that, we're going to use the SimpleCA that is distributed with the toolkit. Here's how we set it up, based on the instructions at SimpleCA Admin:<br /><br />globus@choate:~$ source $GLOBUS_LOCATION/etc/globus-user-env.sh<br />globus@choate:~$ $GLOBUS_LOCATION/setup/globus/setup-simple-ca<br />WARNING: GPT_LOCATION not set, assuming:<br /> GPT_LOCATION=/usr/local/globus-4.0.1<br /> C e r t i f i c a t e A u t h o r i t y S e t u p<br />This script will setup a Certificate Authority for signing Globus<br />users certificates. It will also generate a simple CA package<br />that can be distributed to the users of the CA.<br />The CA information about the certificates it distributes will<br />be kept in:<br />/home/globus/.globus/simpleCA/<br />/usr/local/globus-4.0.1/setup/globus/setup-simple-ca: line 250:<br />test: res: integer expression expected<br />The unique subject name for this CA is:<br />cn=Globus Simple CA, ou=simpleCA-choate.mcs.anl.gov, ou=GlobusTest, o=Grid<br />Do you want to keep this as the CA subject (y/n) [y]:<br />y<br />Enter the email of the CA (this is the email where certificate<br />requests will be sent to be signed by the CA): bacon@choate<br />The CA certificate has an expiration date. Keep in mind that<br />once the CA certificate has expired, all the certificates<br />signed by that CA become invalid. A CA should regenerate<br />the CA certificate and start re-issuing ca-setup packages<br />before the actual CA certificate expires. This can be done<br />by re-running this setup script. Enter the number of DAYS<br />the CA certificate should last before it expires.<br />[default: 5 years (1825 days)]:RETURN<br />Enter PEM pass phrase:******<br />Verifying - Enter PEM pass phrase:******<br />/bin/sed: can't read /tmp//globus_tmp_ca_setup//pkgdata/pkg_data_src.gpt.tmpl:<br />No such file or directory<br />creating CA config package...<br />A self-signed certificate has been generated<br />for the Certificate Authority with the subject:<br />/O=Grid/OU=GlobusTest/OU=simpleCA-choate.mcs.anl.gov/CN=Globus Simple CA<br />If this is invalid, rerun this script<br />/usr/local/globus-4.0.1/setup/globus/setup-simple-ca<br />and enter the appropriate fields.<br />-------------------------------------------------------------------<br />The private key of the CA is stored in /home/globus/.globus/simpleCA//private/cakey.pem<br />The public CA certificate is stored in /home/globus/.globus/simpleCA//cacert.pem<br />The distribution package built for this CA is stored in<br />/home/globus/.globus/simpleCA//globus_simple_ca_ebb88ce5_setup-0.18.tar.gz<br />This file must be distributed to any host wishing to request<br />certificates from this CA.<br />CA setup complete.<br />The following commands will now be run to setup the security<br />configuration files for this CA:<br />$GLOBUS_LOCATION/sbin/gpt-build \<br />/home/globus/.globus/simpleCA//globus_simple_ca_ebb88ce5_setup-0.18.tar.gz<br />$GLOBUS_LOCATION/sbin/gpt-postinstall<br />-------------------------------------------------------------------<br />setup-ssl-utils: Configuring ssl-utils package<br />Running setup-ssl-utils-sh-scripts...<br />***************************************************************************<br />Note: To complete setup of the GSI software you need to run the<br />following script as root to configure your security configuration<br />directory:<br />/usr/local/globus-4.0.1/setup/globus_simple_ca_ebb88ce5_setup/setup-gsi<br />For further information on using the setup-gsi script, use the -help<br />option. The -default option sets this security configuration to be<br />the default, and -nonroot can be used on systems where root access is<br />not available.<br />***************************************************************************<br />setup-ssl-utils: Complete<br />globus@choate:~$ <br /><br />That's quite a lot of output. Here's what has happened:<br /><br />globus@choate:~$ ls ~/.globus/<br />simpleCA<br />globus@choate:~$ ls ~/.globus/simpleCA/<br />cacert.pem globus_simple_ca_ebb88ce5_setup-0.18.tar.gz newcerts<br />certs grid-ca-ssl.conf private<br />crl index.txt serial<br /><br />That's the directory where my simpleCA has been created. Now I need to make my machine trust that new CA, which I do by running the following command as root:<br /><br />globus@choate:~$ exit<br />root@choate:~# export GLOBUS_LOCATION=/usr/local/globus-4.0.1<br />root@choate:~# $GLOBUS_LOCATION/setup/globus_simple_ca_ebb88ce5_setup/setup-gsi -default<br />setup-gsi: Configuring GSI security<br />Making /etc/grid-security...<br />mkdir /etc/grid-security<br />Making trusted certs directory: /etc/grid-security/certificates/<br />mkdir /etc/grid-security/certificates/<br />Installing /etc/grid-security/certificates//grid-security.conf.ebb88ce5...<br />Running grid-security-config...<br />Installing Globus CA certificate into trusted CA certificate directory...<br />Installing Globus CA signing policy into trusted CA certificate directory...<br />setup-gsi: Complete<br />root@choate:~# ls /etc/grid-security/<br />certificates globus-host-ssl.conf globus-user-ssl.conf grid-security.conf<br />root@choate:~# ls /etc/grid-security/certificates/<br />ebb88ce5.0 globus-user-ssl.conf.ebb88ce5<br />ebb88ce5.signing_policy grid-security.conf.ebb88ce5<br />globus-host-ssl.conf.ebb88ce5<br /><br />Those are the configuration files that establish trust for the simpleCA for my Globus Toolkit installation. Notice that the hash value ebb88ce5 matches the hash value of my SimpleCA. These files are all explained in Security Admin. If you don't have root, you can use the -nonroot option to place the files under your GLOBUS_LOCATION instead.<br /><br />Now that we've created a CA and trust it, we'll get a hostcert for the machine:<br /><br />root@choate:~# source $GLOBUS_LOCATION/etc/globus-user-env.sh<br />root@choate:~# grid-cert-request -host `hostname`<br />Generating a 1024 bit RSA private key<br />..++++++<br />...................................................++++++<br />writing new private key to '/etc/grid-security/hostkey.pem'<br />...<br />Your certificate will be mailed to you within two working days.<br />If you receive no response, contact Globus Simple CA at bacon@choate<br /><br />We need to sign the certificate using our simpleCA, as globus:<br /><br />root@choate:~$ su - globus<br />globus@choate:~$ grid-ca-sign -in /etc/grid-security/hostcert_request.pem -out hostsigned.pem<br />To sign the request<br />please enter the password for the CA key:******<br />The new signed certificate is at: /home/globus/.globus/simpleCA//newcerts/01.pem<br /><br />Our last step is to copy that signed certificate into /etc:<br /><br />globus@choate:~$ exit<br />root@choate:~# cp ~globus/hostsigned.pem /etc/grid-security/hostcert.pem <br /><br />The hostcert and hostkey are owned by root, and will be used by the GridFTP server. Because the webservices container runs non-root, we need a certificate owned by globus. In the end, we need one host certificate/key owned by root, and one host certificate/key owned by globus. We do that by copying the files:<br /><br />root@choate:/etc/grid-security# cp hostcert.pem containercert.pem<br />root@choate:/etc/grid-security# cp hostkey.pem containerkey.pem<br />root@choate:/etc/grid-security# chown globus:globus container*.pem<br />root@choate:/etc/grid-security# ls -l *.pem<br />-r-------- 1 globus globus 887 2005-11-15 07:48 containerkey.pem<br />-rw-r--r-- 1 globus globus 2710 2005-11-15 07:48 containercert.pem<br />-rw-r--r-- 1 root root 2710 2005-11-15 07:47 hostcert.pem<br />-rw-r--r-- 1 root root 1404 2005-11-15 07:40 hostcert_request.pem<br />-r-------- 1 root root 887 2005-11-15 07:40 hostkey.pem<br /><br />Now we'll get a usercert for bacon. In this example I'm running tcsh, just to show that the version of globus-user-env depends on your shell:<br /><br />bacon@choate :~$ setenv GLOBUS_LOCATION /usr/local/globus-4.0.1/<br />bacon@choate :~$ source $GLOBUS_LOCATION/etc/globus-user-env.sh<br />bacon@choate :~$ grid-cert-request <br />A certificate request and private key is being created.<br />You will be asked to enter a PEM pass phrase.<br />This pass phrase is akin to your account password,<br />and is used to protect your key file.<br />If you forget your pass phrase, you will need to<br />obtain a new certificate.<br />Generating a 1024 bit RSA private key<br />.........................................................++++++<br />.........................++++++<br />unable to write 'random state'<br />writing new private key to '/home/bacon/.globus/userkey.pem'<br />Enter PEM pass phrase: ****<br />Verifying - Enter PEM pass phrase: ****<br />-----<br />You are about to be asked to enter information that will be incorporated<br />into your certificate request.<br />What you are about to enter is what is called a Distinguished Name or a DN.<br />There are quite a few fields but you can leave some blank<br />-----<br />Level 0 Organization [Grid]:<br />Level 0 Organizational Unit [GlobusTest]:<br />Level 1 Organizational Unit [simpleCA-choate.mcs.anl.gov]:<br />Level 2 Organizational Unit [mcs.anl.gov]:<br />Name (e.g., John M. Smith) []:<br />A private key and a certificate request has been generated with the subject:<br />/O=Grid/OU=GlobusTest/OU=simpleCA-choate.mcs.anl.gov/OU=mcs.anl.gov/CN=Charles Bacon<br />If the CN=Charles Bacon is not appropriate, rerun this<br />script with the -force -cn "Common Name" options.<br />Your private key is stored in /home/bacon/.globus/userkey.pem<br />Your request is stored in /home/bacon/.globus/usercert_request.pem<br />Please e-mail the request to the Globus Simple CA bacon@choate<br />You may use a command similar to the following:<br />cat /home/bacon/.globus/usercert_request.pem | mail bacon@choate<br />Only use the above if this machine can send AND receive e-mail. if not, please<br />mail using some other method.<br />Your certificate will be mailed to you within two working days.<br />If you receive no response, contact Globus Simple CA at bacon@choate<br /><br />Now I need to get that certificate request to the globus user so it can be signed, then send the signed cert back to bacon:<br /><br />bacon@choate :~$ cat /home/bacon/.globus/usercert_request.pem | mail globus@choate<br /><br />Please note that the point of the "mail" command is to move the request from the second machine to the first machine. I need it on the first machine because that's where SimpleCA is installed. You can use scp or some other tool to move the request over to choate. Once it is on choate, sign it as user globus:<br /><br />bacon@choate :~$ exit<br />root@choate :~$ su - globus<br />globus@choate:~$ grid-ca-sign -in request.pem -out signed.pem<br />To sign the request<br />please enter the password for the CA key: ******<br />The new signed certificate is at: /home/globus/.globus/simpleCA//newcerts/02.pem<br />globus@choate:~$ cat signed.pem | mail bacon@choate<br /><br />Now user bacon checks his mail and copies the cert to the proper location:<br /><br />globus@choate :~$ exit<br />bacon@choate :~$ su - bacon<br />bacon@choate :~$ cp signed.pem ~/.globus/usercert.pem<br />bacon@choate :~$ ls -l ~/.globus/<br />total 12<br />-rw-r--r-- 1 bacon globdev 895 2005-11-15 07:57 usercert.pem<br />-rw-r--r-- 1 bacon globdev 1426 2005-11-15 07:51 usercert_request.pem<br />-r-------- 1 bacon globdev 963 2005-11-15 07:51 userkey.pem<br /><br />Our last act will be to create a grid-mapfile as root for authorization:<br /><br />root@choate:/etc/grid-security# vim /etc/grid-security/grid-mapfile<br />root@choate:/etc/grid-security# cat /etc/grid-security/grid-mapfile <br />"/O=Grid/OU=GlobusTest/OU=simpleCA-choate.mcs.anl.gov/OU=mcs.anl.gov/CN=Charles Bacon" bacon<br /><br /> [Note]<br /> <br /><br /> Note<br /> <br /> <br /><br /> The globus user doesn't need a user certificate! It's a dummy account that we're using to own the GLOBUS_LOCATION. When it starts the container, it will use the containercert. Only real people need user certs.<br /><br />2.4. Set up GridFTP<br /><br />Now that we have our secure credentials in place, we can start a service. This setup comes from the GridFTP Admin Guide.<br /><br />root@choate:/etc/grid-security# vim /etc/xinetd.d/gridftp<br />root@choate:/etc/grid-security# cat /etc/xinetd.d/gridftp<br />service gsiftp<br />{<br />instances = 100<br />socket_type = stream<br />wait = no<br />user = root<br />env += GLOBUS_LOCATION=/usr/local/globus-4.0.1<br />env += LD_LIBRARY_PATH=/usr/local/globus-4.0.1/lib <br />server = /usr/local/globus-4.0.1/sbin/globus-gridftp-server<br />server_args = -i<br />log_on_success += DURATION<br />nice = 10<br />disable = no<br />}<br />root@choate:/etc/grid-security# vim /etc/services <br />root@choate:/etc/grid-security# tail /etc/services <br />vboxd 20012/udp<br />binkp 24554/tcp # binkp fidonet protocol<br />asp 27374/tcp # Address Search Protocol<br />asp 27374/udp<br />dircproxy 57000/tcp # Detachable IRC Proxy<br />tfido 60177/tcp # fidonet EMSI over telnet<br />fido 60179/tcp # fidonet EMSI over TCP<br /># Local services<br />gsiftp 2811/tcp<br />root@choate:/etc/grid-security# /etc/init.d/xinetd reload<br />Reloading internet superserver configuration: xinetd.<br />root@choate:/etc/grid-security# netstat -an | grep 2811<br />tcp 0 0 0.0.0.0:2811 0.0.0.0:* LISTEN <br /><br />Now the gridftp server is waiting for a request, so we'll run a client and transfer a file:<br /><br />bacon@choate :~$ grid-proxy-init -verify -debug<br />User Cert File: /home/bacon/.globus/usercert.pem<br />User Key File: /home/bacon/.globus/userkey.pem<br />Trusted CA Cert Dir: /etc/grid-security/certificates<br />Output File: /tmp/x509up_u1817<br />Your identity: /O=Grid/OU=GlobusTest/OU=simpleCA-choate.mcs.anl.gov/OU=mcs.anl.gov/CN=Charles Bacon<br />Enter GRID pass phrase for this identity: ****<br />Creating proxy .....++++++++++++<br />..++++++++++++<br />Done<br />Proxy Verify OK<br />Your proxy is valid until: Tue Nov 15 20:15:46 2005<br />bacon@choate :~$ globus-url-copy gsiftp://choate.mcs.anl.gov/etc/group file:///tmp/bacon.test.copy<br />bacon@choate :~$ diff /tmp/bacon.test.copy /etc/group<br />bacon@choate :~$ <br /><br />The globus-url-copy takes two arguments, the source and the destination. In this case we're using the gsiftp:// to indicate a GridFTP transfer from the host choate.mcs.anl.gov of the file /etc/group as the source. The destination is just going to be a file on the local system under /tmp/bacon.test.copy.<br /><br />Okay, so the GridFTP server works. If you had trouble, start with the GridFTP Troubleshooting guide. If the trouble is with your certificates, check the security troubleshooting. Now we can move on to starting the webservices container.<br />2.5. Starting the webservices container<br /><br />Now we'll setup an /etc/init.d entry for the webservices container. You can find more details about the container at Container Admin Guide.<br /><br />globus@choate:~$ vim $GLOBUS_LOCATION/start-stop<br />globus@choate:~$ cat $GLOBUS_LOCATION/start-stop<br />#! /bin/sh<br />set -e<br />export GLOBUS_LOCATION=/usr/local/globus-4.0.1<br />export JAVA_HOME=/opt/java<br />export ANT_HOME=/opt/ant<br />export GLOBUS_OPTIONS="-Xms256M -Xmx512M" <br />. $GLOBUS_LOCATION/etc/globus-user-env.sh<br />cd $GLOBUS_LOCATION<br />case "$1" in<br /> start)<br /> $GLOBUS_LOCATION/sbin/globus-start-container-detached -p 8443<br /> ;;<br /> stop)<br /> $GLOBUS_LOCATION/sbin/globus-stop-container-detached<br /> ;;<br /> *)<br /> echo "Usage: globus {start|stop}" >&2<br /> exit 1<br /> ;;<br />esac<br />exit 0<br />globus@choate:~$ chmod +x $GLOBUS_LOCATION/start-stop<br />Now, as root, we'll create an /etc/init.d script to call the globus user's start-stop script: <br />root@choate:~# vim /etc/init.d/globus-4.0.1<br />root@choate:~# cat /etc/init.d/globus-4.0.1 <br />#!/bin/sh -e<br />case "$1" in<br />start)<br /> su - globus /usr/local/globus-4.0.1/start-stop start<br /> ;;<br />stop)<br /> su - globus /usr/local/globus-4.0.1/start-stop stop<br /> ;;<br />restart)<br /> $0 stop<br /> sleep 1<br /> $0 start<br /> ;;<br />*)<br /> printf "Usage: $0 {start|stop|restart}\n" >&2<br /> exit 1<br /> ;;<br />esac<br />exit 0<br />root@choate:~# chmod +x /etc/init.d/globus-4.0.1 <br />root@choate:~# /etc/init.d/globus-4.0.1 start<br />Starting Globus container. PID: 29985<br />root@choate:~# cat /usr/local/globus-4.0.1/var/container.log<br />2005-11-15 08:48:00,886 ERROR service.ReliableFileTransferImpl [main,:68]<br />Unable to setup database driver with pooling.A connection error has occurred:<br />FATAL: no pg_hba.conf entry for host "140.221.8.31", user "globus",<br />database "rftDatabase", SSL off <br />2005-11-15 08:48:02,183 WARN service.ReliableFileTransferHome [main,initialize:97]<br />All RFT requests will fail and all GRAM jobs that require file staging will fail.<br />A connection error has occurred: FATAL: no pg_hba.conf entry for host<br />"140.221.8.31", user "globus", database "rftDatabase", SSL off<br />Starting SOAP server at: https://140.221.8.31:8443/wsrf/services/ <br />With the following services:<br />[1]: https://140.221.8.31:8443/wsrf/services/TriggerFactoryService<br />[2]: https://140.221.8.31:8443/wsrf/services/DelegationTestService<br />[3]: https://140.221.8.31:8443/wsrf/services/SecureCounterService<br />[4]: https://140.221.8.31:8443/wsrf/services/IndexServiceEntry<br />[5]: https://140.221.8.31:8443/wsrf/services/DelegationService<br />[6]: https://140.221.8.31:8443/wsrf/services/InMemoryServiceGroupFactory<br />[7]: https://140.221.8.31:8443/wsrf/services/mds/test/execsource/IndexService<br />[8]: https://140.221.8.31:8443/wsrf/services/mds/test/subsource/IndexService<br />[9]: https://140.221.8.31:8443/wsrf/services/SubscriptionManagerService<br />[10]: https://140.221.8.31:8443/wsrf/services/TestServiceWrongWSDL<br />[11]: https://140.221.8.31:8443/wsrf/services/SampleAuthzService<br />[12]: https://140.221.8.31:8443/wsrf/services/WidgetNotificationService<br />[13]: https://140.221.8.31:8443/wsrf/services/AdminService<br />[14]: https://140.221.8.31:8443/wsrf/services/DefaultIndexServiceEntry<br />[15]: https://140.221.8.31:8443/wsrf/services/CounterService<br />[16]: https://140.221.8.31:8443/wsrf/services/TestService<br />[17]: https://140.221.8.31:8443/wsrf/services/InMemoryServiceGroup<br />[18]: https://140.221.8.31:8443/wsrf/services/SecurityTestService<br />[19]: https://140.221.8.31:8443/wsrf/services/ContainerRegistryEntryService<br />[20]: https://140.221.8.31:8443/wsrf/services/NotificationConsumerFactoryService<br />[21]: https://140.221.8.31:8443/wsrf/services/TestServiceRequest<br />[22]: https://140.221.8.31:8443/wsrf/services/IndexFactoryService<br />[23]: https://140.221.8.31:8443/wsrf/services/ReliableFileTransferService<br />[24]: https://140.221.8.31:8443/wsrf/services/mds/test/subsource/IndexServiceEntry<br />[25]: https://140.221.8.31:8443/wsrf/services/Version<br />[26]: https://140.221.8.31:8443/wsrf/services/NotificationConsumerService<br />[27]: https://140.221.8.31:8443/wsrf/services/IndexService<br />[28]: https://140.221.8.31:8443/wsrf/services/NotificationTestService<br />[29]: https://140.221.8.31:8443/wsrf/services/ReliableFileTransferFactoryService<br />[30]: https://140.221.8.31:8443/wsrf/services/DefaultTriggerServiceEntry<br />[31]: https://140.221.8.31:8443/wsrf/services/TriggerServiceEntry<br />[32]: https://140.221.8.31:8443/wsrf/services/PersistenceTestSubscriptionManager<br />[33]: https://140.221.8.31:8443/wsrf/services/mds/test/execsource/IndexServiceEntry<br />[34]: https://140.221.8.31:8443/wsrf/services/DefaultTriggerService<br />[35]: https://140.221.8.31:8443/wsrf/services/TriggerService<br />[36]: https://140.221.8.31:8443/wsrf/services/gsi/AuthenticationService<br />[37]: https://140.221.8.31:8443/wsrf/services/TestRPCService<br />[38]: https://140.221.8.31:8443/wsrf/services/ManagedMultiJobService<br />[39]: https://140.221.8.31:8443/wsrf/services/RendezvousFactoryService<br />[40]: https://140.221.8.31:8443/wsrf/services/WidgetService<br />[41]: https://140.221.8.31:8443/wsrf/services/ManagementService<br />[42]: https://140.221.8.31:8443/wsrf/services/ManagedExecutableJobService<br />[43]: https://140.221.8.31:8443/wsrf/services/InMemoryServiceGroupEntry<br />[44]: https://140.221.8.31:8443/wsrf/services/AuthzCalloutTestService<br />[45]: https://140.221.8.31:8443/wsrf/services/DelegationFactoryService<br />[46]: https://140.221.8.31:8443/wsrf/services/DefaultIndexService<br />[47]: https://140.221.8.31:8443/wsrf/services/ShutdownService<br />[48]: https://140.221.8.31:8443/wsrf/services/ContainerRegistryService<br />[49]: https://140.221.8.31:8443/wsrf/services/TestAuthzService<br />[50]: https://140.221.8.31:8443/wsrf/services/CASService<br />[51]: https://140.221.8.31:8443/wsrf/services/ManagedJobFactoryService<br />2005-11-15 08:48:29,063 INFO impl.DefaultIndexService [ServiceThread-10,processConfigFile:107]<br />Reading default registration configuration from file:<br />/usr/local/globus-4.0.1/etc/globus_wsrf_mds_index/hierarchy.xml<br />2005-11-15 08:48:31,705 ERROR impl.QueryAggregatorSource [Thread-12,pollGetMultiple:149]<br />Exception Getting Multiple Resource Properties from<br />https://140.221.8.31:8443/wsrf/services/ReliableFileTransferFactoryService:<br />java.rmi.RemoteException: Failed to serialize resource property<br />org.globus.transfer.reliable.service.factory.TotalNumberOfBytesTransferred@e8eeca;<br />nested exception is:<br /> org.apache.commons.dbcp.DbcpException: A connection error has occurred:<br />FATAL: no pg_hba.conf entry for host "140.221.8.31", user "globus",<br />database "rftDatabase", SSL off<br /><br />1<br /> <br /><br />The RFT warnings are expected right now because we haven't setup our database yet. Otherwise, things look good.<br /><br />2<br /> <br /><br />140.221.8.31 is my IP address. Some people following the quickstart may see "127.0.0.1" here. You need to fix that! Edit $GLOBUS_LOCATION/etc/globus_wsrf_core/server-config.wsdd and client-server-config.wsdd, add a line reading 140.221.8.32" /> under the section. For instance:<br /><br />You can also use this to select the interface to publish for a multi-homed host. See Global Configuration for more container config options.<br /><br />At this point, we can use one of the sample clients/services to interact with the container:<br /><br />choate % setenv JAVA_HOME /usr/java/j2sdk1.4.2_10/<br />choate % setenv ANT_HOME /usr/local/apache-ant-1.6.5/<br />choate % setenv PATH $ANT_HOME/bin:$JAVA_HOME/bin:$PATH<br />choate % counter-client -s https://choate.mcs.anl.gov:8443/wsrf/services/CounterService<br />Got notification with value: 3<br />Counter has value: 3<br />Got notification with value: 13<br /><br /> <br /><br />Whenever you see me testing against "choate.mcs.anl.gov" in this document, use your own fully qualified hostname. Connections to choate will timeout because the host is behind a firewall.<br /><br />That is the expected output, so it looks like the container is up and running. Next we'll configure a database for RFT to get rid of that pesky warning, and so we can reliably transfer files using GridFTP!<br />2.6. Configuring RFT<br /><br />Following the instructions at RFT Admin, we'll first configure the system to allow TCP/IP connections to postgres, as well as adding a trust entry for our current host. More recent versions of postgres have deprecated the "-i" option. For version 8 and newer, instead set "listen_addresses = '*'" in the postgres configuration file.<br /><br />root@choate:~# vim /var/lib/psql/data/pg_hba.conf <br />root@choate:~# grep rftDatabase /etc/postgresql/pg_hba.conf <br />host rftDatabase "globus" "140.221.8.31" 255.255.255.255 md5<br />root@choate:~# /etc/init.d/postgresql restart<br />Stopping PostgreSQL database server: postmaster.<br />Starting PostgreSQL database server: postmaster.<br />root@choate:~# su postgres -c "createuser -P globus"<br />Enter password for new user: *****<br />Enter it again: *****<br />Shall the new user be allowed to create databases? (y/n) y<br />Shall the new user be allowed to create more new users? (y/n) n<br />CREATE USER<br /><br /> [Note]<br /> <br /><br /> Note<br /> <br /> <br /><br /> This is one of the most system-dependent steps of this quickstart. Your pg_hba.conf and postmaster.conf files may be located in a different directory. Please consult your vendor's notes for details.<br /><br />Now the globus user can create the rftDatabase:<br /><br />globus@choate:~$ createdb rftDatabase<br />CREATE DATABASE<br />globus@choate:~$ psql -d rftDatabase -f $GLOBUS_LOCATION/share/globus_wsrf_rft/rft_schema.sql<br />psql:/usr/local/globus-4.0.1/share/globus_wsrf_rft/rft_schema.sql:6: NOTICE:<br />CREATE TABLE / PRIMARY KEY will create implicit index "requestid_pkey" for table "requestid"<br />CREATE TABLE<br />psql:/usr/local/globus-4.0.1/share/globus_wsrf_rft/rft_schema.sql:11: NOTICE:<br />CREATE TABLE / PRIMARY KEY will create implicit index "transferid_pkey" for table "transferid"<br />CREATE TABLE<br />psql:/usr/local/globus-4.0.1/share/globus_wsrf_rft/rft_schema.sql:30: NOTICE:<br />CREATE TABLE / PRIMARY KEY will create implicit index "request_pkey" for table "request"<br />CREATE TABLE<br />psql:/usr/local/globus-4.0.1/share/globus_wsrf_rft/rft_schema.sql:65: NOTICE:<br />CREATE TABLE / PRIMARY KEY will create implicit index "transfer_pkey" for table "transfer"<br />CREATE TABLE<br />CREATE TABLE<br />CREATE TABLE<br />CREATE INDEX<br />globus@choate:~$ vim $GLOBUS_LOCATION/etc/globus_wsrf_rft/jndi-config.xml<br />globus@choate:~$ grep -C 3 password $GLOBUS_LOCATION/etc/globus_wsrf_rft/jndi-config.xml <br /> <br /> <br /> <br /> password<br /> <br /> <br /> *****<br /><br />I have created the database, loaded the RFT schema, and changed the password in the jndi-config.xml file. If your database isn't owned by the same user as the container, you will also need to change the username parameter in the jndi-config.xml. In this example, we installed as globus and made the database as globus, so I only changed the password.<br /><br />The database is setup, so we restart the container to load the new RFT configuration:<br /><br />root@choate:~# /etc/init.d/globus-4.0.1 restart<br />Stopping Globus container. PID: 29985<br />Starting Globus container. PID: 8620<br />root@choate:~# head /usr/local/globus-4.0.1/var/container.log<br />Starting SOAP server at: https://140.221.8.31:8443/wsrf/services/<br />With the following services:<br />[1]: https://140.221.8.31:8443/wsrf/services/TriggerFactoryService<br />[2]: https://140.221.8.31:8443/wsrf/services/DelegationTestService<br />[3]: https://140.221.8.31:8443/wsrf/services/SecureCounterService<br />[4]: https://140.221.8.31:8443/wsrf/services/IndexServiceEntry<br />[5]: https://140.221.8.31:8443/wsrf/services/DelegationService<br />[6]: https://140.221.8.31:8443/wsrf/services/InMemoryServiceGroupFactory<br />[7]: https://140.221.8.31:8443/wsrf/services/mds/test/execsource/IndexService<br />...<br /><br />Great, we got rid of the warning. Now let's try an RFT transfer to make sure the service is really working:<br /><br />bacon@choate :~$ cp /usr/local/globus-4.0.1/share/globus_wsrf_rft_test/transfer.xfr /tmp/rft.xfr<br />bacon@choate :~$ vim /tmp/rft.xfr <br />bacon@choate :~$ cat /tmp/rft.xfr <br />true<br />16000<br />16000<br />false<br />1<br />true<br />1<br />null<br />null<br />false<br />10<br />gsiftp://choate.mcs.anl.gov:2811/etc/group<br />gsiftp://choate.mcs.anl.gov:2811/tmp/rftTest_Done.tmp<br />bacon@choate :~$ rft -h choate.mcs.anl.gov -f /tmp/rft.xfr <br />Number of transfers in this request: 1<br />Subscribed for overall status<br />Termination time to set: 60 minutes<br />Overall status of transfer:<br />Finished/Active/Failed/Retrying/Pending<br />0/1/0/0/0<br />Overall status of transfer:<br />Finished/Active/Failed/Retrying/Pending<br />1/0/0/0/0<br />All Transfers are completed<br />bacon@choate :~$ diff /etc/group /tmp/rftTest_Done.tmp <br />bacon@choate :~$<br /><br />RFT did its job, starting up a reliable transfer and notifying us of the status and results.<br />2.7. Setting up WS GRAM<br /><br />Now that we have GridFTP and RFT working, we can setup GRAM for resource management. First we have to setup sudo so the globus user can start jobs as a different user. For reference, you can see the GRAM Admin Guide.<br /><br />root@choate:~# visudo<br />root@choate:~# cat /etc/sudoers <br />globus ALL=(bacon) NOPASSWD: /usr/local/globus-4.0.1/libexec/globus-gridmap-and-execute<br />-g /etc/grid-security/grid-mapfile /usr/local/globus-4.0.1/libexec/globus-job-manager-script.pl *<br />globus ALL=(bacon) NOPASSWD: /usr/local/globus-4.0.1/libexec/globus-gridmap-and-execute<br />-g /etc/grid-security/grid-mapfile /usr/local/globus-4.0.1/libexec/globus-gram-local-proxy-tool *<br /><br />Make sure they're all on one line. I split them up in the HTML to keep the page width down. Also, if your sudoers has a line reading "requiretty", remove it. The container won't have a tty while it is running, but it needs to use sudo. With that addition, we can now run jobs:<br /><br />bacon@choate :~$ globusrun-ws -submit -c /bin/true<br />Submitting job...Done.<br />Job ID: uuid:3304e3f2-55f2-11da-8b8f-00d0b7b7c0bc<br />Termination time: 11/16/2005 16:09 GMT<br />Current job state: Active<br />Current job state: CleanUp<br />Current job state: Done<br />Destroying job...Done.<br />bacon@choate :~$ echo $?<br />0<br />choate % globusrun-ws -submit -c /bin/false<br />Submitting job...Done.<br />Job ID: uuid:456b7c9a-55f2-11da-9b0d-00d0b7b7c0bc<br />Termination time: 11/16/2005 16:09 GMT<br />Current job state: Active<br />Current job state: CleanUp<br />Current job state: Done<br />Destroying job...Done.<br />bacon@choate :~$ echo $?<br />1<br /><br />Success. Now we've got a working GRAM installation.<br />3. Setting up your second machine<br />3.1. Setting up your second machine: Prereqs<br /><br />Alas, it's not much of a grid with just one machine. So let's start up on another machine and add it to this little test grid. For a change of pace, I'm going to use the binary installer on this machine. First, though, let's get some prereqs out of the way:<br /><br />root@cognito:~# cd /opt<br />root@cognito:~# ./jdk-6u13-linux-i586.bin<br />root@cognito:~# mv jdk1.6.0_13 java<br /><br />Next, we download from here, install ant:<br /><br />root@cognito:~# cd /opt<br />root@cognito:~# tar xzf apache-ant-1.7.1-bin.tar.gz<br />root@cognito:~# mv apache-ant-1.7.1 ant<br /><br />Also need to set JAVA_HOME and ANT_HOME<br />Add below entry in /etc/profile<br /><br />export JAVA_HOME=/opt/java<br />export ANT_HOME=/opt/ant<br />export GLOBUS_LOCATION=/usr/local/globus-4.0.1<br />export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$GLOBUS_LOCATION/bin:$GLOBUS_LOCATION/sbin:$PATH<br />root@cognito:~# adduser globus<br />root@cognito:~# mkdir /usr/local/globus-4.0.1<br />root@cognito:~# chown globus:globus /usr/local/globus-4.0.1<br /><br />Then, as user globus: <br />globus@cognito:~$ tar xzf gt4.0.8-all-source-installer.tar.gz<br /><br /> [Note]<br /> <br /><br /> Note<br /> <br /> <br /><br /> You might notice that I didn't install Postgres on this machine. That's because my grid can actually share the services of the RFT located on my first machine. Even if I weren't planning on that, I could add this new machine to the pg_hba.conf on the first machine and re-use the existing DB server.<br /><br />3.2. Setting up your second machine: Installation<br /><br />Now we can install from binaries:<br /><br />globus@cognito:~/gt4.0.8-all-source-installer$ ./configure \<br /> --prefix=/usr/local/globus-4.0.1<br />checking for javac... /usr/java/j2sdk1.4.2_10//bin/javac<br />checking for ant... /usr/local/apache-ant-1.6.5//bin/ant<br />configure: creating ./config.status<br />config.status: creating Makefile<br />globus@cognito:~/gt4.0.8-all-source-installer$ make<br />cd gpt-3.2autotools2004 && OBJECT_MODE=32 ./build_gpt<br />...<br />Binaries are much faster! This is done in less than 10 minutes.<br />...<br />tar -C /usr/local/globus-4.0.1 -xzf binary-trees/globus_wsrf_rft_test-*/*.tar.gz<br />tar -C /usr/local/globus-4.0.1 -xzf binary-trees/globus_rendezvous-*/*.tar.gz<br />echo "Your build completed successfully. Please run make install."<br />Your build completed successfully. Please run make install.<br />globus@cognito:~/gt4.0.8-all-source-installer$ make install<br />ln -s /usr/local/globus-4.0.1/etc/gpt/packages /usr/local/globus-4.0.1/etc/globus_packages<br />...<br />config.status: creating fork.pm<br />..Done<br /><br />3.3. Setting up your second machine: Security<br /><br />Now let's get security setup on the second machine. We're going to just add trust for the original simpleCA to this new machine, there's no need to create a new one. This is the multiple machines section of the SimpleCA guide.<br /><br />Please make sure that your two machines agree on the time! These certificates have dates that tell you when they are valid. If your two machines don't agree about the time, you might get errors saying a certificate is not yet valid. If you use NTP, this won't be a problem.<br /><br />globus@cognito:~$ scp choate:.globus/simpleCA/globus_simple_ca_ebb88ce5_setup-0.18.tar.gz .<br /><br />globus@cognito:~$ $GLOBUS_LOCATION/sbin/gpt-build globus_simple_ca_ebb88ce5_setup-0.18.tar.gz <br />gpt-build ====> CHECKING BUILD DEPENDENCIES FOR globus_simple_ca_ebb88ce5_setup<br />gpt-build ====> Changing to /sandbox/globus/BUILD/globus_simple_ca_ebb88ce5_setup-0.18/<br />gpt-build ====> BUILDING globus_simple_ca_ebb88ce5_setup<br />gpt-build ====> Changing to /sandbox/globus/BUILD<br />gpt-build ====> REMOVING empty package globus_simple_ca_ebb88ce5_setup-noflavor-data<br />gpt-build ====> REMOVING empty package globus_simple_ca_ebb88ce5_setup-noflavor-dev<br />gpt-build ====> REMOVING empty package globus_simple_ca_ebb88ce5_setup-noflavor-doc<br />gpt-build ====> REMOVING empty package globus_simple_ca_ebb88ce5_setup-noflavor-pgm_static<br />gpt-build ====> REMOVING empty package globus_simple_ca_ebb88ce5_setup-noflavor-rtl<br />globus@cognito:~$ $GLOBUS_LOCATION/sbin/gpt-postinstall<br />running /usr/local/globus-4.0.1/setup/globus/./setup-ssl-utils.ebb88ce5..<br />[ Changing to /usr/local/globus-4.0.1/setup/globus/. ]<br />...<br />setup-ssl-utils: Complete<br />..Done<br />WARNING: The following packages were not set up correctly:<br /> globus_simple_ca_ebb88ce5_setup-noflavor-pgm<br />Check the package documentation or run postinstall -verbose to see what happened<br /><br />That installed the package, but the warning is letting us know that root still needs to run the setup script:<br /><br />globus@cognito:~$ exit<br />root@cognito:~# source $GLOBUS_LOCATION/etc/globus-user-env.sh<br />root@cognito:~# $GLOBUS_LOCATION/setup/globus_simple_ca_ebb88ce5_setup/setup-gsi -default<br />setup-gsi: Configuring GSI security<br />Making /etc/grid-security...<br />mkdir /etc/grid-security<br />Making trusted certs directory: /etc/grid-security/certificates/<br />mkdir /etc/grid-security/certificates/<br />Installing /etc/grid-security/certificates//grid-security.conf.ebb88ce5...<br />Running grid-security-config...<br />nstalling Globus CA certificate into trusted CA certificate directory...<br />Installing Globus CA signing policy into trusted CA certificate directory...<br />setup-gsi: Complete<br /><br />Now our new machine's security directory looks like our other machine:<br /><br />root@cognito:~# ls /etc/grid-security/<br />certificates globus-host-ssl.conf globus-user-ssl.conf grid-security.conf<br />root@cognito:~# ls /etc/grid-security/certificates/<br />ebb88ce5.0 globus-user-ssl.conf.ebb88ce5<br />ebb88ce5.signing_policy grid-security.conf.ebb88ce5<br />globus-host-ssl.conf.ebb88ce5<br /><br />Now we need a hostcert for the new machine:<br /><br />root@cognito:~# grid-cert-request -host `hostname`<br />The hostname cognito does not appear to be fully qualified.<br />Do you wish to continue? [n] n<br />Aborting<br />...<br />If you receive no response, contact Globus Simple CA at bacon@choate<br />root@cognito:~# hostname<br />cognito<br /><br />Uh-oh. Our hostname isn't fully qualified, which is going to cause us trouble down the road. If you have this problem, there are several possible solutions. One is to run the hostname command as root to set your FQDN as your hostname. Another possibility is that your /etc/hosts may have a short name listed for your IP address. Let's see what the problem is on cognito:<br /><br />root@cognito:~# host 140.221.8.109<br /><br />109.8.221.140.in-addr.arpa domain name pointer cognito.mcs.anl.gov.<br /><br />If the problem had been in /etc/hosts, I would have fixed it. Here's what a good /etc/hosts line would look like:<br /><br />140.221.8.109 cognito.mcs.anl.gov cognito<br /><br />Since reverse lookups work okay, I will just spell out the FQDN by hand in this cert request:<br /><br />root@cognito:~# grid-cert-request -host cognito.mcs.anl.gov -force<br /> /etc/grid-security/hostcert_request.pem already exists<br /> /etc/grid-security/hostcert.pem already exists<br /> /etc/grid-security/hostkey.pem already exists<br />...<br />Your certificate will be mailed to you within two working days.<br />If you receive no response, contact Globus Simple CA at bacon@choate<br /><br />The request already existed for "cognito", but the -force overwrote that request with one for "cognito.mcs.anl.gov". Now I need to copy that back to choate and sign it:<br /><br />root@cognito:~# scp /etc/grid-security/hostcert_request.pem globus@choate:/home/globus<br /><br />Now I sign it as globus on choate. Remember, that's where I installed the SimpleCA, so that's where I sign it:<br /><br />globus@choate:/tmp$ grid-ca-sign -in hostcert_request.pem -out out.pem<br />To sign the request<br />please enter the password for the CA key:<br />The new signed certificate is at: /home/globus/.globus/simpleCA//newcerts/03.pem<br />globus@choate:/tmp$ scp /tmp/out.pem root@cognito:/root/<br /><br />Root checks his email, then saves the signed cert:<br /><br />root@cognito:~# cp out.pem /etc/grid-security/hostcert.pem <br />root@cognito:~# cd /etc/grid-security<br />root@cognito:/etc/grid-security# cp hostcert.pem containercert.pem<br />root@cognito:/etc/grid-security# cp hostkey.pem containerkey.pem<br />root@cognito:/etc/grid-security# chown globus:globus container*.pem<br />root@cognito:/etc/grid-security# ls -l *.pem<br />-rw-r--r-- 1 globus globus 2711 2005-11-15 11:14 containercert.pem<br />-r-------- 1 globus globus 887 2005-11-15 11:15 containerkey.pem<br />-rw-r--r-- 1 root root 2711 2005-11-15 11:14 hostcert.pem<br />-rw-r--r-- 1 root root 1405 2005-11-15 11:09 hostcert_request.pem<br />-r-------- 1 root root 887 2005-11-15 11:09 hostkey.pem<br /><br />There. Now cognito is setup with host and container certs, and it trusts the CA of my grid. The last step for root is to create a grid-mapfile for myself again:<br /><br />root@cognito:/etc/grid-security# vim grid-mapfile<br />root@cognito:/etc/grid-security# cat grid-mapfile <br />"/O=Grid/OU=GlobusTest/OU=simpleCA-choate.mcs.anl.gov/OU=mcs.anl.gov/CN=Charles Bacon" bacon<br /><br />Also, user bacon should get a local copy of the usercert:<br /><br />root@cognito:/etc/grid-security# su – bacon<br />cognito % scp -r choate:.globus .<br />Password:<br />usercert.pem 100% 895 0.9KB/s 00:00 <br />usercert_request.pem 100% 1426 1.4KB/s 00:00 <br />userkey.pem 100% 963 0.9KB/s 00:00 <br /><br />3.4. Setting up your second machine: GridFTP<br /><br />GridFTP setup on the second machine is identical to the first. I'll just list the commands here, see Section 2.4, “Set up GridFTP” for the file contents, or just copy them from the first machine.<br /><br />root@cognito:/etc/grid-security# vim /etc/xinetd.d/gridftp <br />root@cognito:/etc/grid-security# vim /etc/services <br />root@cognito:/etc/grid-security# /etc/init.d/xinetd reload<br />Reloading internet superserver configuration: xinetd.<br /><br />Now we can test it:<br /><br />root@cognito:/etc/grid-security# su - bacon<br />bacon@cognito:~$ source $GLOBUS_LOCATION/etc/globus-user-env.sh<br />bacon@cognito:~$ grid-proxy-init -verify -debug<br />User Cert File: /home/bacon/.globus/usercert.pem<br />User Key File: /home/bacon/.globus/userkey.pem<br />Trusted CA Cert Dir: /etc/grid-security/certificates<br />Output File: /tmp/x509up_u1817<br />Your identity: /O=Grid/OU=GlobusTest/OU=simpleCA-choate.mcs.anl.gov/OU=mcs.anl.gov/CN=Charles Bacon<br />Enter GRID pass phrase for this identity:<br />Creating proxy ...........++++++++++++<br />........++++++++++++<br />Done<br />Proxy Verify OK<br />Your proxy is valid until: Tue Nov 15 23:33:37 2005<br />bacon@cognito:~$ globus-url-copy gsiftp://cognito.mcs.anl.gov/etc/group gsiftp://choate.mcs.anl.gov/tmp/from-cognito<br /><br />That was a slightly fancier test than I ran on choate. In this case, I did a third-party transfer between two GridFTP servers. It worked, so I have the local and remote security setup correctly.<br />3.5. Setting up your second machine: Webservices<br /><br />Setting up the container on the second machine is a lot like the first. I'll list the commands here. See Section 2.5, “Starting the webservices container”, or you can just copy the files from the first machine. First globus creates the start-stop script:<br /><br />globus@cognito:~$ vim $GLOBUS_LOCATION/start-stop<br />globus@cognito:~$ chmod +x $GLOBUS_LOCATION/start-stop<br /><br />Then root creates an init.d script to call it:<br /><br />root@cognito:~# vim /etc/init.d/globus-4.0.1<br />root@cognito:~# chmod +x /etc/init.d/globus-4.0.1<br />root@cognito:/etc/grid-security# /etc/init.d/globus-4.0.1 start<br />Starting Globus container. PID: 17269<br /><br />3.6. Setting up your second machine: WS GRAM<br /><br />For a change of pace, we'll setup GRAM first on the second machine, even though we haven't got a working RFT locally. As with last time, we'll need to setup the sudoers. See Section 2.7, “Setting up WS GRAM” for the sudo contents, or copy the sudoers from the first machine. If you just copy the file, please make sure that you have sudo installed already, and that the permissions are 440.<br /><br />root@cognito:/etc/grid-security# visudo<br /><br />Now we can submit a staging job:<br /><br />bacon@cognito:~$ vim a.rsl<br />bacon@cognito:~$ cat a.rsl<br />bacon@cognito:~$ cat a.rsl<br /> my_echo<br /> ${GLOBUS_USER_HOME}<br /> Hello<br /> World!<br /> ${GLOBUS_USER_HOME}/stdout<br /> ${GLOBUS_USER_HOME}/stderr<br /> <br /> <br /> gsiftp://cognito.mcs.anl.gov:2811/bin/echo<br /> file:///${GLOBUS_USER_HOME}/my_echo<br /> <br /> <br /> <br /> <br /> file:///${GLOBUS_USER_HOME}/my_echo<br /> <br /> <br />bacon@cognito:~$ globusrun-ws -submit -S -f a.rsl<br />Delegating user credentials...Done.<br />Submitting job...Done.<br />Job ID: uuid:6732f346-5604-11da-9951-0002b3882c16<br />Termination time: 11/16/2005 18:19 GMT<br />Current job state: StageIn<br />Current job state: Active<br />Current job state: CleanUp<br />Current job state: Done<br />Destroying job...Done.<br />Cleaning up any delegated credentials...Done.<br />bacon@cognito:~$ cat ~/stdout<br />Hello World!<br />bacon@cognito:~$ ls ~/my_echo<br />ls: /home/bacon/my_echo: No such file or directory<br /><br />This is an example of a staging job. It copies the /bin/echo command from cognito to my home directory and names it my_echo. Then it runs it with some arguments, and captures the stderr/stdout. One of the neat features here is that it used the RFT service on choate to transfer the file via the GridFTP server on cognito. It's starting to look like a Grid!<br /><br />If you got an "invalid executable: my_echo" error, make sure you staged the echo command to the machine where you're executing the job. One way to get this error is by running this on cognito, but staging the file to choate instead. The stageIn will work, but the job will fail because you staged to the wrong host.<br /><br />Also, this won't work if your cognito and choate have different processor architectures. For instance, you can't run an ia64 binary on an ia32 computer. In that case, you could try staging in a shell script instead.<br /><br />You can get other examples of GRAM RSL files from GRAM usage scenarios.<br /><br />Also, you can submit from one machine to another using the -F (factory) option. For instance, to submit from cognito to choate:<br /><br />bacon@cognito:~$ globusrun-ws -F choate -submit -c /bin/true<br />Submitting job...Done.<br />Job ID: uuid:0efba320-4780-11dc-bd6b-0007e9d811ce<br />Termination time: 08/11/2007 20:27 GMT<br />Current job state: Active<br />Current job state: CleanUp<br />Current job state: Done<br />Destroying job...Done.<br /><br />Likewise, you could login to choate and submit a job to cognito. <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://www.blogger.com/profile/08055786710159541445' itemprop='url'/> <a class='g-profile' href='https://www.blogger.com/profile/08055786710159541445' rel='author' title='author profile'> <span itemprop='name'>virendersharma</span> </a> </span> </span> <span class='post-timestamp'> at <meta content='http://virendersharma.blogspot.com/2009/04/globus-toolkit-408-grid-with-weka4ws.html' itemprop='url'/> <a class='timestamp-link' href='https://virendersharma.blogspot.com/2009/04/globus-toolkit-408-grid-with-weka4ws.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2009-04-16T21:29:00-07:00'>9:29 PM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://virendersharma.blogspot.com/2009/04/globus-toolkit-408-grid-with-weka4ws.html#comment-form' onclick=''> 2 comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-463720878'> <a href='https://www.blogger.com/post-edit.g?blogID=7460292314936920729&postID=3907177839402561847&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> <div class='post-outer'> <div class='post hentry uncustomized-post-template' itemprop='blogPost' itemscope='itemscope' itemtype='http://schema.org/BlogPosting'> <meta content='http://www.kernel-panic.it/openbsd/nagios/nagiosdirstruct_small.png' itemprop='image_url'/> <meta content='7460292314936920729' itemprop='blogId'/> <meta content='4489830738780296028' itemprop='postId'/> <a name='4489830738780296028'></a> <h3 class='post-title entry-title' itemprop='name'> <a href='https://virendersharma.blogspot.com/2009/04/network-monitoring-with-nagios-and.html'>Network monitoring with Nagios and OpenBSD</a> </h3> <div class='post-header'> <div class='post-header-line-1'></div> </div> <div class='post-body entry-content' id='post-body-4489830738780296028' itemprop='description articleBody'> <h2>1. Introduction</h2> <p>So our OpenBSD-based network now includes <a href="http://www.kernel-panic.it/openbsd/carp/index.html">redundant firewalls</a>, <a href="http://www.kernel-panic.it/openbsd/dns/index.html">domain name servers</a>, a <a href="http://www.kernel-panic.it/openbsd/mail/index.html">mail gateway</a> and a <a href="http://www.kernel-panic.it/openbsd/proxy/index.html">web proxy cache</a>. All the services provided by these machines are particularly critical and can't afford even minimal downtime. Redundancy may give us the time to recover a failure before having angry users trying to knock down our door, but it doesn't free us from the responsibility to detect and solve ongoing problems.</p> <p>To put it short, it's time to think about monitoring our network! And the following are the perfect ingredients for implementing a full-featured, secure and reliable network monitoring system:</p> <dl><dt><a href="http://www.openbsd.org/">OpenBSD</a></dt><dd>the operating system for the security paranoid, with <q>only two remote holes in the default install, in more than 10 years!</q>;</dd><dt><a href="http://www.nagios.org/">Nagios</a></dt><dd>the <q>leader and industry standard in enterprise system, network, and application monitoring</q>;</dd><dt><a href="http://httpd.apache.org/">Apache</a></dt><dd>the <q>secure, efficient and extensible server that provides <acronym title="HyperText Transfer Protocol">HTTP</acronym> services in sync with the current HTTP standards</q>.</dd></dl> <p>My pick goes to Nagios for its ease of use, flexibility and extensibility. It also features a very clean and straightforward design, as it is structured into three basic building blocks:</p> <ul><li>a <dfn>daemon process</dfn>, running periodic checks on specific hosts and services and managing notifications when problems arise;</li><li>an optional <dfn>web interface</dfn>, to access current status information, historical logs and reports via a simple web browser;</li><li>a set of <dfn>external plugins</dfn>, i.e. the (possibly custom) scripts executed by the daemon process to actually perform the checks and send out notifications.</li></ul> <p>Furthermore, these basic components can be easily extended with external modules, making it easy for Nagios to meet even your most demanding needs! Therefore, after the installation and configuration of the Nagios' core components, we will take a brief look at some of its most popular and useful <a href="http://www.nagiosexchange.org/AddOn_Projects.22.0.html">addons</a>:</p> <ul><li><a href="http://www.kernel-panic.it/openbsd/nagios/nagios5.html#nagios-5.1">NRPE</a>, the <dfn>Nagios Remote Plugin Executor</dfn>, which allows you to execute local plugins on remote hosts;</li><li><a href="http://www.kernel-panic.it/openbsd/nagios/nagios5.html#nagios-5.2">NSCA</a>, the <dfn>Nagios Service Check Acceptor</dfn>, which processes passive service check results submitted by clients to the Nagios server;</li><li><a href="http://www.kernel-panic.it/openbsd/nagios/nagios5.html#nagios-5.3">NagVis</a>, the <dfn>Nagios Visualization Addon</dfn>, which allows you to deeply customize how Nagios data is displayed;</li></ul> <p>A good knowledge of OpenBSD is assumed, since we won't delve into system management topics such as base configuration or packages/ports installation.</p><h2> </h2><h2>2. Installation and base configuration</h2> <p>Before delving straight into the details of Nagios installation and configuration, let's take a brief look at the layout of the <a href="http://www.kernel-panic.it/openbsd/carp/carp2.html#net">network</a> that we're going to monitor. It's a very simple and small network, made up of:</p> <ul><li>a <acronym title="Local Area Network">LAN</acronym> (172.16.0.0/24), containing clients and servers not accessible from the public Internet (e.g. file server, <acronym title="Dynamic Host Configuration Protocol">DHCP</acronym> server);</li><li>a <acronym title="DeMilitarized Zone">DMZ</acronym> (172.16.240.0/24), containing the servers that must access the Internet (e.g. mail, web and proxy servers);</li><li>a router, in a small subnet (172.16.250.0/24), connecting the DMZ to the Internet.</li></ul> <p>Our network monitoring system is a security-critical host and won't need to directly access the Internet, so it will perfectly fit in the internal LAN.</p> <p>The OpenBSD installation procedure is documented in full detail in the <a href="http://www.openbsd.org/faq/faq4.html">official <acronym title="Frequently Asked Questions">FAQ</acronym></a>, so we won't linger on it here. Nagios doesn't have particular requirements and a standard OpenBSD installation will do just fine: according to the <a href="http://nagios.sourceforge.net/docs/3_0/about.html#requirements">documentation</a>, Nagios makes do with just <q>a machine running Linux (or UNIX variant)</q>. That doesn't sound so fussy, does it?</p> <h3><a id="nagios-2.1" name="nagios-2.1"></a>2.1 Packages installation</h3> <p>Nagios installation only requires <a href="http://www.openbsd.org/faq/faq15.html#PkgInstall">adding a few packages</a>:</p> <ul><li>libltdl-<var>x</var>.<var>x</var>.tgz</li><li>libiconv-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>gettext-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>nagios-plugins-<var>x</var>.<var>x</var>.tgz</li><li>nagios-<var>x</var>.<var>x</var>-chroot.tgz</li><li>nagios-web-<var>x</var>.<var>x</var>-chroot.tgz</li></ul> <p>The installation procedure will automatically create the user and group that the monitoring daemon will drop its privileges to (<tt>_nagios</tt>). The <tt>chroot</tt> flavor will install Nagios in a way suited for chrooted <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=httpd&sektion=8">httpd(8)</a></tt>, i.e. with the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html">CGIs</a> statically linked and all the configuration and log files stored inside the <tt>/var/www</tt> directory. By the way, Nagios has a particular directory structure that you will have to become familiar with:</p> <dl><dt><tt>/var/www/nagios/</tt></dt><dd>this directory contains the static <acronym title="HyperText Markup Language">HTML</acronym> pages for the web interface and the online documentation;</dd><dt><tt>/var/www/cgi-bin/nagios/</tt></dt><dd>contains the dynamic <acronym title="Common Gateway Interface">CGI</acronym> pages of the web interface, which actually retrieve and display the current status of the monitored objects;</dd><dt><tt>/var/www/etc/nagios/</tt></dt><dd>you should put all your Nagios configuration files in this directory: we will examine them one by one in a moment;</dd><dt><tt>/var/www/var/log/nagios/</tt></dt><dd>this is the directory where Nagios will create the <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#log_file">log</a>, <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#status_file">status</a> and <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#state_retention_file">retention</a> files;</dd><dt><tt>/var/www/var/log/nagios/archives/</tt></dt><dd>Nagios log files are periodically rotated and moved to this directory;</dd><dt><tt>/var/www/var/nagios/rw/</tt></dt><dd>contains the <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#command_file">external command file</a>;</dd><dt><tt>/usr/local/libexec/nagios/</tt></dt><dd>contains the standard <a href="http://nagios.sourceforge.net/docs/3_0/plugins.html">plugins</a>.</dd></dl> <p>As a reference, below is a visual representation of the directory structure of Nagios, kindly submitted by Bren Smith (click <a href="http://www.kernel-panic.it/openbsd/nagios/nagiosdirstruct.png">here</a> for a larger view).</p> <div class="block-img"> <a href="http://www.kernel-panic.it/openbsd/nagios/nagiosdirstruct.png"><img alt="Directory structure" height="490" src="http://www.kernel-panic.it/openbsd/nagios/nagiosdirstruct_small.png" width="950" /></a> </div> <h3><a id="nagios-2.2" name="nagios-2.2"></a>2.2 Configuration overview</h3> <p>Nagios configuration may look overly complicated at first glance; even the <a href="http://nagios.sourceforge.net/docs/3_0/beginners.html">documentation</a> warns that <q>Nagios is quite powerful and flexible, but it can take a lot of work to get it configured just the way you'd like</q>. Anyway, don't despair! Once you've figured out the underlying logic of its "object-oriented" configuration, you will appreciate Nagios' flexibility and clean design. For the first tests, you can start by tweaking the sample configuration files contained in the <tt>/usr/local/share/examples/nagios/</tt> directory, customizing them to your needs.</p> <p>The syntax of Nagios configuration files follows a few basic rules:</p> <ul><li>comments start with a "<tt>#</tt>" character and span to the end of the line;</li><li>variable names must begin at the start of the line (i.e. no indentation allowed);</li><li>variable names are case sensitive;</li><li>no spaces are allowed around the "<tt>=</tt>" sign.</li></ul> <p>Configuration involves setting several parameters concerning the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.1">monitoring daemon</a>, the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios4.html#nagios-4.1">CGIs</a> and, of course, the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios3.html">hosts and services</a> you want to monitor. All this information is spread among multiple files: we will now examine them one by one.</p> <h4><a id="nagios-2.2.1" name="nagios-2.2.1"></a>2.2.1 The main configuration file</h4> <p>The overall behaviour of the Nagios daemon is determined by the directives included in the main configuration file, <tt>/var/www/etc/nagios/nagios.cfg</tt>. Though this file contains several dozens of parameters, for most of them the default value is the most reasonable option and you will probably want to care about only very few of them (usually <tt><a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#cfg_file">cfg_file</a></tt>, <tt><a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#cfg_dir">cfg_dir</a></tt> and <tt><a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#admin_email">admin_email</a></tt>). In any case, you can find a detailed description of each and every parameter in the official <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html">documentation</a>.</p> <div class="code"> <div>/var/www/etc/nagios/nagios.cfg</div> <pre><i># Path to main log file and log archive directory. All pathnames are relative<br /># to the chroot directory '/var/www/'</i><br />log_file=/var/log/nagios/nagios.log<br />log_archive_path=/var/log/nagios/archives<br /><br /><i># Paths to files managed internally by the application</i><br />object_cache_file=/var/nagios/objects.cache<br />precached_object_file=/var/nagios/objects.precache<br />status_file=/var/nagios/status.dat<br />state_retention_file=/var/nagios/retention.dat<br />command_file=/var/nagios/rw/nagios.cmd<br />lock_file=/var/run/nagios/nagios.pid<br />temp_file=/var/nagios/nagios.tmp<br />temp_path=/tmp<br />check_result_path=/var/spool/nagios<br /><br /><i># Object definitions (see <a href="http://www.kernel-panic.it/openbsd/nagios/nagios3.html">next chapter</a>) can be split across multiple files.<br /># You may either list files individually (using the 'cfg_file' parameter) or<br /># group them into directories (using the 'cfg_dir' parameter). In the latter<br /># case, Nagios will process all files with a '.cfg' extension found in the<br /># specified directories and their subdirectories</i><br />cfg_file=/etc/nagios/timeperiods.cfg<br />cfg_file=/etc/nagios/contacts.cfg<br />cfg_file=/etc/nagios/commands.cfg<br />cfg_file=/etc/nagios/generic-hosts.cfg<br />cfg_file=/etc/nagios/generic-services.cfg<br />cfg_dir=/etc/nagios/hosts<br />cfg_dir=/etc/nagios/services<br /><br /><i># Path to the resource file, containing user-defined macros (see <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.2">below</a>). You can<br /># specify more than one resource file using multiple 'resource_file' statements</i><br />resource_file=/etc/nagios/resource.cfg<br /><br /><i># User and group the Nagios process will run as</i><br />nagios_user=_nagios<br />nagios_group=_nagios<br /><br /><i># Email address and pager number for the administrator of the local machine</i><br />admin_email=nagios@kernel-panic.it<br />admin_pager=xxx-xxx-xxxx<br /><br /><i># Date format (available options: us, euro, iso8601 or strict-iso8601)</i><br />date_format=euro<br /><br /><i># Enable checks, notifications and event handlers. Passive checks allow external<br /># applications to submit check results to Nagios. Event handlers are optional<br /># commands that are executed whenever a host or service state change occurs</i><br />execute_service_checks=1<br />accept_passive_service_checks=1<br />execute_host_checks=1<br />accept_passive_host_checks=1<br />enable_notifications=1<br />enable_event_handlers=1<br /><br /><i># Checks freshness options. Enabling these options will ensure that passive<br /># checks are always up-to-date</i><br />check_service_freshness=1<br />service_freshness_check_interval=60<br />check_host_freshness=0<br />host_freshness_check_interval=60<br />additional_freshness_latency=15<br /><br /><i># External commands allow the web interface and external applications (such as<br /># NSCA) to issue commands to Nagios. With a check interval of '-1', Nagios will<br /># check for external commands as often as possible</i><br />check_external_commands=1<br />command_check_interval=-1<br />external_command_buffer_slots=4096<br /><br /><i># Various logging options</i><br />log_rotation_method=d<br />use_syslog=1<br />log_notifications=1<br />log_service_retries=1<br />log_host_retries=1<br />log_event_handlers=1<br />log_initial_states=0<br />log_external_commands=1<br />log_passive_checks=1<br /><br /><i># Enable retention of state information between program restarts (refer to<br /># <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html#retain_state_information">documentation</a> for details)</i><br />retain_state_information=1<br />retention_update_interval=60<br />use_retained_program_state=1<br />use_retained_scheduling_info=0<br /><br /><i># State flapping detection options (refer to <a href="http://nagios.sourceforge.net/docs/3_0/flapping.html">documentation</a> for details)</i><br />enable_flap_detection=0<br />low_service_flap_threshold=5.0<br />high_service_flap_threshold=20.0<br />low_host_flap_threshold=5.0<br />high_host_flap_threshold=20.0<br /><br /><i># Miscellaneous tuning, performance and security options (refer to<br /># <a href="http://nagios.sourceforge.net/docs/3_0/configmain.html">documentation</a> for details)</i><br />interval_length=60<br />service_inter_check_delay_method=s<br />max_service_check_spread=30<br />service_interleave_factor=s<br />host_inter_check_delay_method=s<br />max_host_check_spread=30<br />max_concurrent_checks=0<br />check_result_reaper_frequency=10<br />max_check_result_reaper_time=30<br />max_check_result_file_age=3600<br />cached_host_check_horizon=15<br />cached_service_check_horizon=15<br />enable_predictive_host_dependency_checks=1<br />enable_predictive_service_dependency_checks=1<br />soft_state_dependencies=0<br />auto_reschedule_checks=0<br />auto_rescheduling_interval=30<br />auto_rescheduling_window=180<br />status_update_interval=15<br />event_broker_options=-1<br /><br />sleep_time=0.25<br />service_check_timeout=60<br />host_check_timeout=30<br />event_handler_timeout=30<br />notification_timeout=30<br />ocsp_timeout=5<br />perfdata_timeout=5<br /><br />use_aggressive_host_checking=0<br />process_performance_data=0<br />obsess_over_services=0<br />obsess_over_hosts=0<br />translate_passive_host_checks=0<br />passive_host_checks_are_soft=0<br /><br />check_for_orphaned_services=0<br />check_for_orphaned_hosts=1<br /><br />p1_file=/usr/local/bin/p1.pl<br />enable_embedded_perl=1<br />use_embedded_perl_implicitly=1<br /><br />illegal_object_name_chars=`~!$%^&*|'"<>?,()=<br />illegal_macro_output_chars=`~$&|'"<><br />use_regexp_matching=0<br />use_true_regexp_matching=0<br />daemon_dumps_core=0<br />use_large_installation_tweaks=0<br />enable_environment_macros=1<br /><br /><i># Debug options</i><br />debug_level=0<br />debug_verbosity=1<br />debug_file=/var/nagios/nagios.debug<br />max_debug_file_size=1000000<br /></pre> </div> <h4><a id="nagios-2.2.2" name="nagios-2.2.2"></a>2.2.2 The resource file</h4> <p>The <dfn>resource file</dfn> allows you to assign values to the user-definable macros "<tt>$USER<var>n</var>$</tt>" (where <tt><var>n</var></tt> is a number between 1 and 32 inclusive). Basically, in Nagios, macros are variables (starting and ending with a dollar sign, "<tt>$</tt>") that you can insert into <a href="http://www.kernel-panic.it/openbsd/nagios/nagios3.html#nagios-3.2">command definitions</a> and that will get expanded to the appropriate value immediately prior to the execution of the command. User-defined macros (and the several other <a href="http://nagios.sourceforge.net/docs/3_0/macros.html">macros</a> Nagios makes available) allow you to keep command definitions generic and simple (see the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios3.html#nagios-3.2">next chapter</a> for some examples).</p> <p>User-defined macros are normally used to store recurring items in command definitions (like directory paths) and sensitive information (like usernames and passwords). It is recommended that you set restrictive permissions (<tt>600</tt>) on the resource file(s) in order to keep sensitive information protected.</p> <div class="code"> <div>/var/www/etc/nagios/resource.cfg</div> <pre><i># Set $USER1$ to be the path to the plugins</i><br />$USER1$=/usr/local/libexec/nagios<br /><br /><i># MySQL username and password</i><br />$USER2$=root<br />$USER3$=password<br /></pre> </div> <p>The next step is configuring object data, which is probably the trickiest part of the configuration. We will therefore devote the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios3.html">next chapter</a> entirely to this topic.</p><h2>3.0 Object data configuration</h2> <p>So now it's time to tell Nagios what to keep tabs on. Therefore, we must supply it with information about:</p> <ul><li><em>when</em> and <em>how</em> to perform checks and send out notifications;</li><li><em>whom</em> to notify;</li><li><em>which</em> hosts and services to monitor.</li></ul> <p>All this information is represented by means of <dfn>objects</dfn>, which are defined by a set of "<tt>define</tt>" <dfn>statements</dfn>, enclosed in curly braces and containing a variable number of newline-separated <dfn>directives</dfn>, in keyword/value form. Keywords are separated from values by whitespace and multiple values can be separated by commas; indentation within statements is allowed.</p> <p>To recap, the basic syntax of an object declaration can be represented as follows:</p> <div> <pre>define <var>object</var> {<br /> <var>keyword-1</var> <var>value-1</var><br /> <var>keyword-2</var> <var>value-2</var>,<var>value-3</var>,...<br /> [...]<br /> <var>keyword-n</var> <var>value-n</var><br />}<br /></pre> </div> <p>Object definitions can be split into any number of files: just remember to list them all in the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.1" target="_blank">main configuration file</a> by using the <tt>cfg_file</tt> and/or <tt>cfg_dir</tt> directives.</p> <h3><a name="0.1_nagios-3.1"></a>3.1 Timeperiod definition</h3> <p>The <tt>timeperiod</tt> statement allows you to specify, for each day of the week, one or more time slots in which to run certain checks and/or notify certain people. Time intervals can't span across midnight and excluded days are simply omitted.</p> <p>In the following example, all the <tt>timeperiod</tt> definitions are grouped together in a file named <tt>timeperiods.cfg</tt> stored in the <tt>/var/www/etc/nagios/</tt> directory.</p> <div> <div>/var/www/etc/nagios/<wbr>timeperiods.cfg</div> <pre><i># The following timeperiod definition includes normal work hours. The<br /># 'timeperiod_name' and 'alias' directives are mandatory. Note that weekend days<br /># are simply omitted</i><br />define timeperiod {<br /> timeperiod_name workhours<br /> alias Work Hours<br /> monday 09:00-18:00<br /> tuesday 09:00-18:00<br /> wednesday 09:00-18:00<br /> thursday 09:00-18:00<br /> friday 09:00-18:00<br />}<br /><br /><i># The following timeperiod includes all time outside normal work hours. The<br /># time slot between 6 p.m. and 9 a.m. must be split into two intervals, to avoid<br /># crossing midnight</i><br />define timeperiod {<br /> timeperiod_name nonworkhours<br /> alias Non-Work Hours<br /> sunday 00:00-24:00<br /> monday 00:00-09:00,18:00-24:00<br /> tuesday 00:00-09:00,18:00-24:00<br /> wednesday 00:00-09:00,18:00-24:00<br /> thursday 00:00-09:00,18:00-24:00<br /> friday 00:00-09:00,18:00-24:00<br /> saturday 00:00-24:00<br />}<br /><br /><i># Most checks will probably run on a continuous basis</i><br />define timeperiod {<br /> timeperiod_name always<br /> alias Every Hour Every Day<br /> sunday 00:00-24:00<br /> monday 00:00-24:00<br /> tuesday 00:00-24:00<br /> wednesday 00:00-24:00<br /> thursday 00:00-24:00<br /> friday 00:00-24:00<br /> saturday 00:00-24:00<br />}<br /><br /><i># The right timeperiod when you don't want to bother with notifications (e.g.<br /># on vacation or during testing)</i><br />define timeperiod {<br /> timeperiod_name never<br /> alias No Time is a Good Time<br />}<br /><br /><i># Some exceptions to the normal weekly time (see <a href="http://nagios.sourceforge.net/docs/3_0/objectdefinitions.html#timeperiod" target="_blank">documentation</a> for more examples)</i><br />define timeperiod {<br /> timeperiod_name exceptions<br /> alias Some random dates<br /> 2008-12-15 00:00-24:00 <i>; December 15th, 2008</i><br /> friday 3 00:00-24:00 <i>; 3rd Friday of every month</i><br /> february -1 00:00-24:00 <i>; Last day in February of every year</i><br /> march 20 - june 21 00:00-24:00 <i>; Spring</i><br /> day 1 - 15 00:00-24:00 <i>; First half of every month</i><br /> 2008-01-01 / 7 00:00-24:00 <i>; Every 7 days from Jan 1st, 2008</i><br />}<br /></pre> </div> <h3><a name="0.1_nagios-3.2"></a>3.2 Command definition</h3> <p>The next step is to tell Nagios <em>how</em> to perform the various checks and send out notifications; this is accomplished by defining multiple <tt>command</tt> objects specifying the actual commands for Nagios to run.</p> <p>Command definitions are pairs of short names and command lines (both mandatory) and can contain <dfn>macros</dfn>. As we mentioned <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.2" target="_blank">before</a>, macros are variables, enclosed in "<tt>$</tt>" signs, that will get expanded to the appropriate value immediately prior to the execution of a command; macros allow you to keep command definitions generic and straightforward. A simple example will make this clear.</p> <p>Suppose you want to monitor a web server with IP address "1.2.3.4"; you could then define a command such as the following:</p> <div> <pre>define command {<br /> command_name check-http<br /> command_line /usr/local/libexec/nagios/<wbr>check_http -I 1.2.3.4<br />}<br /></pre> </div> <p>This definition is correct and will certainly do the job. But what if you later decide to add a new web server? Would you find it convenient to define a new (almost identical) command, with only the IP address changed? It is way more efficient to take advantage of macros by writing a single generic command such as:</p> <div> <pre>define command {<br /> command_name check-http<br /> command_line $USER1$/check_http -I $HOSTADDRESS$<br />}<br /></pre> </div> <p>and leave Nagios the responsibility to expand the built-in <tt>$HOSTADDRESS$</tt> macro to the appropriate IP address, obtained from the host definition (see <a href="http://mail.google.com/mail/?ui=2&ik=944834bccc&view=att&th=120652c0ccd9fb98&attid=0.1&disp=inline&realattid=f_ft1j99x21&zw#0.1_nagios-3.4">below</a>). As you'll remember from the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.2" target="_blank">previous chapter</a>, the <tt>$USER1$</tt> macro holds the path to the plugins directory.</p> <p>Now let's complicate things a bit! What if you want Nagios to check the availability of a particular <acronym title="Uniform Resource Locator">URL</acronym> on each web server? This URL may differ from server to server, so what we need now is a command definition that is still generic and yet server-specific! Though this may sound contradictory, once again Nagios solves this problem with macros: in fact, the <tt>$ARG<var>n</var>$</tt> macros (where <tt><var>n</var></tt> is a number between 1 and 32 inclusive) act as placeholders for service-specific arguments that will be specified later within service definitions (see <a href="http://mail.google.com/mail/?ui=2&ik=944834bccc&view=att&th=120652c0ccd9fb98&attid=0.1&disp=inline&realattid=f_ft1j99x21&zw#0.1_nagios-3.5">below</a> for further details). Therefore, the above command definition would turn into:</p> <div> <pre>define command {<br /> command_name check-http<br /> command_line $USER1$/check_http -I $HOSTADDRESS$ -u $ARG1$<br />}<br /></pre> </div> <p>In addition to the ones we have just seen, Nagios provides several other useful macros. Please refer to the <a href="http://nagios.sourceforge.net/docs/3_0/macros.html" target="_blank">documentation</a> for a detailed list of all available macros and their validity context. Below is a sample set of command definitions.</p> <div> <div>/var/www/etc/nagios/commands.<wbr>cfg</div> <pre><i>##############################<wbr>##############################<wbr>####################<br /># Notification commands #<br /># There are no standard notification plugins; hence notification commands are #<br /># usually custom scripts or mere command lines. #<br />##############################<wbr>##############################<wbr>####################</i><br />define command {<br /> command_name host-notify-by-email<br /> command_line $USER1$/host_notify_by_email.<wbr>sh $CONTACTEMAIL$<br />}<br /><br />define command {<br /> command_name notify-by-email<br /> command_line $USER1$/notify_by_email.sh $CONTACTEMAIL$<br />}<br /><br />define command {<br /> command_name host-notify-by-SMS<br /> command_line /usr/local/bin/sendsms $ADDRESS1$ "Nagios: Host $HOSTNAME$ ($HOSTADDRESS$)is in state: $HOSTSTATE$"<br />}<br /><br />define command {<br /> command_name notify-by-SMS<br /> command_line /usr/local/bin/sendsms $ADDRESS1$ "Nagios: Service $SERVICEDESC$ on $HOSTALIAS$ is in state: $SERVICESTATE$"<br />}<br /><br /><i>##############################<wbr>##############################<wbr>####################<br /># Check commands #<br /># The official Nagios plugins should handle most of your needs for host and #<br /># service checks. Anyway, should they not, we will discuss <a href="http://www.kernel-panic.it/openbsd/nagios/nagios6.html" target="_blank">in a moment</a> how to #<br /># write custom plugins. #<br />##############################<wbr>##############################<wbr>####################</i><br />define command {<br /> command_name check-host-alive<br /> command_line $USER1$/check_ping -H $HOSTADDRESS$ -w 3000.0,80% -c 5000.0,100% -p 1<br />}<br /><br />define command {<br /> command_name check-ssh<br /> command_line $USER1$/check_ssh $HOSTADDRESS$<br />}<br /><br />define command {<br /> command_name check-http<br /> command_line $USER1$/check_http -I $HOSTADDRESS$ -u $ARG1$<br />}<br /><br />define command {<br /> command_name check-smtp<br /> command_line $USER1$/check_smtp -H $HOSTADDRESS$<br />}<br /><br />define command {<br /> command_name check-imap<br /> command_line $USER1$/check_imap -H $HOSTADDRESS$<br />}<br /><br />define command {<br /> command_name check-dns<br /> command_line $USER1$/check_dns -s $HOSTADDRESS$ -H $ARG1$ -a $ARG2$<br />}<br /><br />define command {<br /> command_name check-mysql<br /> command_line $USER1$/check_mysql -H $HOSTADDRESS -u $USER2$ -p $USER3$<br />}<br /><br />[...]<br /></pre> </div> <h3><a name="0.1_nagios-3.3"></a>3.3 Contact definition</h3> <p><tt>contact</tt> objects allow you to specify people who should be notified automatically when the alert conditions are met. Contacts are first defined individually and then grouped together in <tt>contactgroup</tt> objects, for easier management.</p> <p>For the first time, in the following definitions, we will refer to previously defined objects. In fact, the values of the <tt>host_notification_period</tt> and <tt>service_notification_period</tt> directives must be <a href="http://mail.google.com/mail/?ui=2&ik=944834bccc&view=att&th=120652c0ccd9fb98&attid=0.1&disp=inline&realattid=f_ft1j99x21&zw#0.1_nagios-3.1"><tt>timeperiod</tt> objects</a>; and the values of the <tt>host_notification_command</tt> and <tt>service_notification_command</tt> directives must be <a href="http://mail.google.com/mail/?ui=2&ik=944834bccc&view=att&th=120652c0ccd9fb98&attid=0.1&disp=inline&realattid=f_ft1j99x21&zw#0.1_nagios-3.2"><tt>command</tt> objects</a>.</p> <div> <div>/var/www/etc/nagios/contacts.<wbr>cfg</div> <pre>define contact {<br /><i># Short name to identify the contact</i><br /> contact_name john<br /><i># Longer name or description</i><br /> alias John Doe<br /><br /><i># Enable notifications for this contact</i><br /> host_notifications_enabled 1<br /> service_notifications_enabled 1<br /><br /><i># Timeperiods during which the contact can be notified about host and service<br /># problems or recoveries</i><br /> host_notification_period always<br /> service_notification_period always<br /><br /><i># Host states for which notifications can be sent out to this contact<br /># (d=down, u=unreachable, r=recovery, f=<a href="http://nagios.sourceforge.net/docs/3_0/flapping.html" target="_blank">flapping</a>, n=none)</i><br /> host_notification_options d,u,r<br /><br /><i># Service states for which notifications can be sent out to this contact<br /># (w=warning, c=critical, u=unknown, r=recovery, f=<a href="http://nagios.sourceforge.net/docs/3_0/flapping.html" target="_blank">flapping</a>, n=none)</i><br /> service_notification_options w,u,c,r<br /><br /><i># Command(s) used to notify the contact about host and service problems<br /># or recoveries</i><br /> host_notification_commands host-notify-by-email,host-<wbr>notify-by-SMS<br /> service_notification_commands notify-by-email,notify-by-SMS<br /><br /><i># Email address for the contact</i><br /> email <a href="mailto:jdoe@kernel-panic.it" target="_blank">jdoe@kernel-panic.it</a><br /><br /><i># Nagios provides 6 address directives (named address1 through address6) to<br /># specify additional "addresses" for the contact (e.g. a mobile phone number<br /># for SMS notifications)</i><br /> address1 xxx-xxx-xxxx<br /><br /><i># Allow this contact to submit <a href="http://nagios.sourceforge.net/docs/3_0/extcommands.html" target="_blank">external commands</a> to Nagios from the CGIs</i><br /> can_submit_commands 1<br />}<br /><br /><i># The following contact is split in two, to allow for different notification<br /># options depending on the timeperiod</i><br />define contact {<br /> contact_name danix@work<br /> alias Daniele Mazzocchio<br /> host_notifications_enabled 1<br /> service_notifications_enabled 1<br /> host_notification_period workhours<br /> service_notification_period workhours<br /> host_notification_options d,u,r<br /> service_notification_options w,u,c,r<br /> host_notification_commands host-notify-by-email<br /> service_notification_commands notify-by-email<br /> email <a href="mailto:danix@kernel-panic.it" target="_blank">danix@kernel-panic.it</a><br /> can_submit_commands 1<br />}<br /><br />define contact {<br /> contact_name danix@home<br /> alias Daniele Mazzocchio<br /> host_notifications_enabled 1<br /> service_notifications_enabled 1<br /> host_notification_period nonworkhours<br /> service_notification_period nonworkhours<br /> host_notification_options d,u<br /> service_notification_options c<br /> host_notification_commands host-notify-by-email,host-<wbr>notify-by-SMS<br /> service_notification_commands notify-by-email,notify-by-SMS<br /> email <a href="mailto:danix@kernel-panic.it" target="_blank">danix@kernel-panic.it</a><br /> address1 xxx-xxx-xxxx<br /> can_submit_commands 1<br />}<br /><br />[...]<br /><br /><i># All administrator contacts are grouped together in the "Admins"<br /># contactgroup</i><br />define contactgroup {<br /> contactgroup_name Admins<br /> alias Nagios Administrators<br /> members danix@work,danix@home,john<br />}<br /><br />[...]<br /></pre> </div> <h3><a name="0.1_nagios-3.4"></a>3.4 Host definition</h3> <p>Now we have finally come to one of the most important facets of Nagios configuration: the definition of the hosts (servers, workstations, devices, etc.) that we want to monitor. This will lead us to introduce one of the most powerful features of Nagios configuration: <a href="http://nagios.sourceforge.net/docs/3_0/objectinheritance.html" target="_blank"><dfn>object inheritance</dfn></a>. Note that, though we are discussing it now first, object inheritance applies to all Nagios objects; however, it's in the definition of hosts and services that you can get the most out of it.</p> <p>In fact, configuring a host requires setting up quite a few parameters; and the value of these parameters will normally be the same for most hosts. Without object inheritance, this would mean wasting a lot of time typing the same parameters over and over again and eventually ending up with cluttered, overweight and almost unmanageable configuration files.</p> <p>But luckily, Nagios is smart enough to save you a lot of typing by allowing you to define special <dfn>template</dfn> objects, whose properties can be "inherited" by other objects without having to rewrite them. Below is a brief example of how a template is created:</p> <div> <pre>define host {<br /> name generic-host-template <i># Template name</i><br /><br /> check_command check-host-alive<br /> check_period always<br /> max_check_attempts 5<br /> notification_options d,u,r<br /><br /> register 0 <i># Don't register it!</i><br />}<br /></pre> </div> <p>As you can see, a template definition looks almost identical to a normal object definition. The only differences are:</p> <ul><li>every template must be assigned a name with the <tt>name</tt> directive;</li><li>since this is not an actual host, you must tell Nagios not to <dfn>register</dfn> it by setting the value of the <tt>register</tt> directive to 0; this property doesn't get inherited and defaults to 1, so you won't need to explicitely override it in all "children" objects;</li><li>a template object can be left <dfn>incomplete</dfn>, i.e. it may not supply all mandatory parameters.</li></ul> <p>To create an actual host object from a template, you simply have to specify the template name as the value of the <tt>use</tt> directive and make sure that all mandatory fields are either inherited or explicitely set:</p> <div> <pre>define host {<br /> host_name <var>hostname</var><br /> use generic-host-template<br /> alias <var>alias</var><br /> address <var>x</var>.<var>x</var>.<var>x</var>.<var>x</var><br />}<br /></pre> </div> <p>Well, now let's move from theory to practice and define two host templates for our servers. Note that the second one inherits from the first; this is possible because Nagios allows multiple levels of template objects.</p> <div> <div>/var/www/etc/nagios/generic-<wbr>hosts.cfg</div> <pre><i># The following is a template for all hosts in the LAN</i><br />define host {<br /><i># Template name</i><br /> name generic-lan-host<br /><br /><i># Command to use to check the state of the host</i><br /> check_command check-host-alive<br /><br /><i># Contact groups to notify about problems (or recoveries) with this host</i><br /> contact_groups Admins<br /><br /><i># Enable active checks</i><br /> active_checks_enabled 1<br /><i># Time period during which active checks of this host can be made</i><br /> check_period always<br /><i># Number of times that Nagios will repeat a check returning a non-OK state</i><br /> max_check_attempts 3<br /><br /><i># Enable the <a href="http://nagios.sourceforge.net/docs/3_0/eventhandlers.html" target="_blank">event handler</a></i><br /> event_handler_enabled 1<br /><br /><i># Enable the processing of <a href="http://nagios.sourceforge.net/docs/3_0/perfdata.html" target="_blank">performance data</a></i><br /> process_perf_data 1<br /><br /><i># Enable retention of host status information across program restarts</i><br /> retain_status_information 1<br /><i># Enable retention of host non-status information across program restarts</i><br /> retain_nonstatus_information 1<br /><br /><i># Enable notifications</i><br /> notifications_enabled 1<br /><i># Time interval (in minutes) between consecutive notifications about the<br /># server being _still_ down or unreachable</i><br /> notification_interval 120<br /><i># Time period during which notifications about this host can be sent out</i><br /> notification_period always<br /><i># Host states for which notifications should be sent out (d=down,<br /># u=unreachable, r=recovery, f=<a href="http://nagios.sourceforge.net/docs/3_0/flapping.html" target="_blank">flapping</a>, n=none)</i><br /> notification_options d,u,r<br /><br /><i># Don't register this definition: it's only a template, not an actual host</i><br /> register 0<br />}<br /><br /><i># DMZ hosts inherit all attributes from the generic-lan-host by means of the<br /># 'use' directive. The only difference is that Nagios has to go through the<br /># internal (CARP) firewalls to reach the DMZ servers, thus requiring the<br /># additional 'parents' directive.</i><br />define host {<br /> name generic-dmz-host<br /><br /><i># The 'use' directive specifies the name of a template object that you want<br /># this host to inherit properties from</i><br /> use generic-lan-host<br /><br /><i># This directive specifies the hosts that lie between the monitoring host<br /># and the remote host (more information <a href="http://nagios.sourceforge.net/docs/3_0/networkreachability.html" target="_blank">here</a>)</i><br /> parents fw-int<br /><br /><i># This too is a template</i><br /> register 0<br />}<br /></pre> </div> <p>Now we can take advantage of our templates to define the actual hosts in a few lines.</p> <div> <div>/var/www/etc/nagios/hosts/<wbr>servers.cfg</div> <pre><i># Configuration for host <a href="http://dns1.lan.kernel-panic.it/" target="_blank">dns1.lan.kernel-panic.it</a></i><br />define host {<br /> use generic-lan-host<br /> host_name dns1<br /> alias LAN primary master name server<br /> address 172.16.0.161<br /><br /><i># Extended information</i><br /> notes This is the internal primary master name server (Bind 9.4.2-P2)<br /><i># URL with more information about this host</i><br /> notes_url <a href="http://www.kernel-panic.it/openbsd/dns/index.html" target="_blank">http://www.kernel-panic.it/<wbr>openbsd/dns/</a><br /><i># Image associated with this host in the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#status_cgi" target="_blank">status</a> CGI; images must be placed in<br /># /var/www/nagios/images/logos/</i><br /> icon_image dns.png<br /><i># String used in the 'alt' tag of the icon_image</i><br /> icon_image_alt [dns]<br /><i># Image associated with this host in the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#statusmap_cgi" target="_blank">statusmap</a> CGI</i><br /> statusmap_image dns.gd2<br />}<br /><br /><i># Configuration for host <a href="http://mail.kernel-panic.it/" target="_blank">mail.kernel-panic.it</a></i><br />define host {<br /> use generic-dmz-host<br /> host_name mail<br /> alias Mail server<br /> address 172.16.240.150<br /> notes This is the Postfix mail server (with IMAP(S) and web access)<br /> notes_url <a href="http://www.kernel-panic.it/openbsd/mail/index.html" target="_blank">http://www.kernel-panic.it/<wbr>openbsd/mail/</a><br /> icon_image mail.png<br /> icon_image_alt [Mail]<br /> statusmap_image mail.gd2<br />}<br /><br /><i># Configuration for host <a href="http://proxy.kernel-panic.it/" target="_blank">proxy.kernel-panic.it</a></i><br />define host {<br /> use generic-dmz-host<br /> host_name proxy<br /> alias Proxy server<br /> notes This is the Squid proxy server<br /> notes_url <a href="http://www.kernel-panic.it/openbsd/proxy/index.html" target="_blank">http://www.kernel-panic.it/<wbr>openbsd/proxy/</a><br /> icon_image proxy.png<br /> icon_image_alt [Proxy]<br /> statusmap_image proxy.gd2<br />}<br /><br />[...]<br /></pre> </div> <div> <div>/var/www/etc/nagios/hosts/<wbr>firewalls.cfg</div> <pre><i># Configuration for host <a href="http://fw-int.kernel-panic.it/" target="_blank">fw-int.kernel-panic.it</a></i><br />define host {<br /> use generic-lan-host<br /> host_name fw-int<br /> alias Internal firewalls' CARP address<br /> address 172.16.0.202<br /> notes Virtual CARP address of the internal firewalls<br /> notes_url <a href="http://www.kernel-panic.it/openbsd/carp/index.html" target="_blank">http://www.kernel-panic.it/<wbr>openbsd/carp/</a><br /> icon_image fw.png<br /> icon_image_alt [FW]<br /> statusmap_image fw.gd2<br />}<br /><br /># Configuration for host <a href="http://mickey.kernel-panic.it/" target="_blank">mickey.kernel-panic.it</a><br />define host {<br /> use generic-lan-host<br /> host_name mickey<br /> alias Internal Firewall #1<br /> address 172.16.0.200<br /> notes Internal firewall (first node of a two-nodes CARP cluster)<br /> notes_url <a href="http://www.kernel-panic.it/openbsd/carp/index.html" target="_blank">http://www.kernel-panic.it/<wbr>openbsd/carp/</a><br /> icon_image fw.png<br /> icon_image_alt [FW]<br /> statusmap_image fw.gd2<br />}<br /><br />[...]<br /></pre> </div> <p>Hosts can optionally be grouped together with the <tt>hostgroup</tt> statement, which has no effect on monitoring, but simply allows you to display the hosts in groups in the CGIs.</p> <div> <div>/var/www/etc/nagios/hosts/<wbr>hostgroups.cfg</div> <pre><i># Domain Name Servers</i><br />define hostgroup {<br /> hostgroup_name DNS<br /> alias Domain Name Servers<br /> members dns1,dns2,dns3,dns4<br /> notes Our internal Domain Name Servers, running Bind 9.4.2-P2<br />}<br /><br /><i># Firewalls</i><br />define hostgroup {<br /> hostgroup_name firewalls<br /> alias CARP Firewalls<br /> members mickey,minnie,donald,daisy,fw-<wbr>int,fw-ext<br /> notes Our CARP-enabled firewalls (both virtual and physical addresses)<br />}<br /><br /><i># Web servers</i><br />define hostgroup {<br /> hostgroup_name WWW<br /> alias Web Servers<br /> members www1,www2<br /> notes Our corporate web servers, running Apache 1.3<br />}<br /></pre> </div> <h3><a name="0.1_nagios-3.5"></a>3.5 Service definition</h3> <p>Configuring the services to monitor is much like configuring hosts: object inheritance can save you a lot of typing and you can group services together with the optional <tt>servicegroup</tt> statement. Below is the definition of our service template:</p> <div> <div>/var/www/etc/nagios/generic-<wbr>services.cfg</div> <pre>define service {<br /><i># Template name</i><br /> name generic-service<br /><br /><i># Services are normally not <a href="http://nagios.sourceforge.net/docs/3_0/volatileservices.html" target="_blank">volatile</a></i><br /> is_volatile 0<br /><br /><i># Contact groups to notify about problems (or recoveries) with this service</i><br /> contact_groups Admins<br /><br /><i># Enable active checks</i><br /> active_checks_enabled 1<br /><i># Time period during which active checks of this service can be made</i><br /> check_period always<br /><i># Time interval (in minutes) between "regular" checks, i.e. checks that<br /># occur when the service is in an OK state or when the service is in a non-OK<br /># state, but has already been re-checked max_check_attempts number of times</i><br /> normal_check_interval 5<br /><i># Time interval (in minutes) between non-regular checks</i><br /> retry_check_interval 1<br /><i># Number of times that Nagios will repeat a check returning a non-OK state</i><br /> max_check_attempts 3<br /><i># Enable service check parallelization for better performance</i><br /> parallelize_check 1<br /><i># Enable passive checks</i><br /> passive_checks_enabled 1<br /><br /><i># Enable the <a href="http://nagios.sourceforge.net/docs/3_0/eventhandlers.html" target="_blank">event handler</a></i><br /> event_handler_enabled 1<br /><br /><i># Enable the processing of <a href="http://nagios.sourceforge.net/docs/3_0/perfdata.html" target="_blank">performance data</a></i><br /> process_perf_data 1<br /><br /><i># Enable retention of service status information across program restarts</i><br /> retain_status_information 1<br /><i># Enable retention of service non-status information across program restarts</i><br /> retain_nonstatus_information 1<br /><br /><i># Enable notifications</i><br /> notifications_enabled 1<br /><i># Time interval (in minutes) between consecutive notifications about the<br /># service being _still_ in non-OK state</i><br /> notification_interval 120<br /><i># Time period during which notifications about this service can be sent out</i><br /> notification_period always<br /><i># Service states for which notifications should be sent out (c=critical,<br /># w=warning, u=unknown, r=recovery, f=<a href="http://nagios.sourceforge.net/docs/3_0/flapping.html" target="_blank">flapping</a>, n=none)</i><br /> notification_options w,u,c,r<br /><br /> register 0<br />}<br /></pre> </div> <p>Now, before moving to services definitions, we should complete our <a href="http://mail.google.com/mail/?ui=2&ik=944834bccc&view=att&th=120652c0ccd9fb98&attid=0.1&disp=inline&realattid=f_ft1j99x21&zw#0.1_nagios-3.2">discussion</a> on passing service-specific arguments to commands by means of the <tt>$ARG<var>n</var>$</tt> macros. As you'll remember, these macros act as placeholders: they expand to the <var>n</var>th argument passed to the command in the service definition; for instance, a command definition such as the following expects to be passed two arguments:</p> <div> <pre>define command {<br /> command_name some-command<br /> command_line $USER1$/check_something $ARG1$ $ARG2$<br />}<br /></pre> </div> <p>Therefore, to configure a service check to use the above command, we will need to assign the <tt>check_command</tt> variable a string containing the command's short name followed by the arguments, separated by "<tt>!</tt>" characters. E.g.:</p> <div> <pre>define service {<br /> service_description some-service<br /> check_command some-command!arg-1!arg-2<br /> [...]<br />}<br /></pre> </div> <p>Now we can proceed to the definition of the actual services:</p> <div> <div>/var/www/etc/nagios/services/<wbr>services.cfg</div> <pre><i># Secure Shell service</i><br />define service {<br /> use generic-service<br /> service_description SSH<br /><i># Short name(s) of the host(s) that run this service. If a service runs on all<br /># hosts, you may use the '*' wildcard character</i><br /> host_name *<br /> check_command check-ssh<br /><i># This directive is a possible alternative to using the members directive in<br /># service groups definitions</i><br /> servicegroups ssh-services<br /><i># Extended information</i><br /> notes Availability of the SSH daemon<br /> notes_url <a href="http://www.openssh.org/" target="_blank">http://www.openssh.org/</a><br /> icon_image ssh.png<br /> icon_image_alt [SSH]<br />}<br /><br /><i># Web service</i><br />define service {<br /> use generic-service<br /> service_description WWW<br /> host_name www1,www2<br /> check_command check-http!/index.html<br /> notes Availability of the corporate web sites<br /> notes_url <a href="http://www.apache.org/" target="_blank">http://www.apache.org/</a><br /> icon_image www.png<br /> icon_image_alt [WWW]<br />}<br /><br />define service {<br /> use generic-service<br /> service_description WWW<br /> host_name mail<br /> check_command check-http!/webmail/index.html<br /> notes Availability of the web access to the mail server<br /> notes_url <a href="http://www.squirrelmail.org/" target="_blank">http://www.squirrelmail.org/</a><br /> icon_image www.png<br /> icon_image_alt [WWW]<br />}<br /><br />[...]<br /></pre> </div> <p>Just like hosts, services can be grouped together with the <tt>servicegroup</tt> directive:</p> <div> <div>/var/www/etc/nagios/services/<wbr>servicegroups.cfg</div> <pre>define servicegroup {<br /> servicegroup_name www-services<br /> alias Web Services<br /><i># The 'members' directive requires a comma-separated list of host and<br /># service pairs, e.g. 'host1,service1,host2,<wbr>service2,...'</i><br /> members www1,WWW,www2,WWW,mail,WWW<br />}<br /><br />define servicegroup {<br /> servicegroup_name dns-services<br /> alias Domain Name Service<br /> members dns1,DNS,dns2,DNS,dns3,DNS,<wbr>dns4,DNS<br />}<br /><br /><i># The members of the following servicegroup are specified with the<br /># 'serviecegroups' directive in the 'SSH' service definition</i><br />define servicegroup {<br /> servicegroup_name ssh-services<br /> alias Secure Shell Service<br />}<br /><br />[...]<br /></pre> </div> <p>Well, the bulk of the work is over now: the last step is <a href="http://www.kernel-panic.it/openbsd/nagios/nagios4.html" target="_blank">configuring the web interface</a> and then we will finally be able to set our Nagios server to work!</p><p><br /></p><h2>4. Setting up the web interface</h2> <p>Nagios doesn't have a specific client application to access the monitoring information; instead, it relies on the <a href="http://httpd.apache.org/">Apache</a> web server to provide a very simple yet powerful web interface, accessible via any browser and allowing users to access current status information, browse historical logs, create reports and, if so configured, issue commands to the monitoring daemon.</p> <h3><a id="nagios-4.1" name="nagios-4.1"></a>4.1 CGIs configuration</h3> <p>Nagios' web interface relies on a series of <acronym title="Common Gateway Interface">CGI</acronym> programs written in C. The CGIs read their configuration information from two files: the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.1">main configuration file</a> and <tt>cgi.cfg</tt>, located, by default, in the <tt>/var/www/etc/nagios/</tt> directory.</p> <p>Below is a sample configuration file; pay particular attention when setting the <tt>authorized_for_*</tt> directives, because they allow you to assign special privileges to authenticated users and are, therefore, highly security critical. In the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios4.html#nagios-4.2">next section</a>, we will review how to create users in Apache.</p> <div class="code"> <div>/var/www/etc/nagios/cgi.cfg</div> <pre><i># Path to the main configuration file (relative to the chroot)</i><br />main_config_file=/etc/nagios/nagios.cfg<br /><i># Path to the directory where the HTML files reside (relative to the chroot)</i><br />physical_html_path=/nagios<br /><i># Path portion of the URL used to access the web interface</i><br />url_html_path=/nagios<br /><br /><i># Disable context-sensitive help</i><br />show_context_help=0<br /><br /><i># Enable authentication for the CGIs</i><br />use_authentication=1<br /><i># Uncomment the following directive to set a default user for unauthenticated<br /># sessions (strongly discouraged)<br />#default_user_name=guest</i><br /><br /><i># The 'authorized_for_*' directives define a comma-separated list of<br /># authenticated web users who can:<br /># - view system/process information in the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#extinfo_cgi">extended information CGI</a>:</i><br />authorized_for_system_information=nagiosadmin,operator<br /><i># - view configuration information in the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#config_cgi">configuration CGI</a>:</i><br />authorized_for_configuration_information=nagiosadmin,operator<br /><i># - issue system/process commands via the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#cmd_cgi">command CGI</a>:</i><br />authorized_for_system_commands=nagiosadmin<br /><i># - view status and configuration information for all services</i><br />authorized_for_all_services=nagiosadmin,operator<br /><i># - view status and configuration information for all hosts</i><br />authorized_for_all_hosts=nagiosadmin,operator<br /><i># - issue commands for all services via the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#cmd_cgi">command CGI</a>:</i><br />authorized_for_all_service_commands=nagiosadmin<br /><i># - issue commands for all hosts via the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#cmd_cgi">command CGI</a>:</i><br />authorized_for_all_host_commands=nagiosadmin<br /><br /><i># Options for the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#statusmap_cgi">Status Map</a> and <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#statuswrl_cgi">Status World</a> CGIs</i><br />statusmap_background_image=smbackground.gd2<br />default_statusmap_layout=5<br />default_statuswrl_layout=4<br />statuswrl_include=myworld.wrl<br /><br /><i># Command to use when attempting to ping a host from the <a href="http://nagios.sourceforge.net/docs/3_0/cgis.html#statuswml_cgi">WAP interface</a></i><br />ping_syntax=/sbin/ping -n -c 5 $HOSTADDRESS$<br /><br /><i># Time interval (in seconds) between page refreshes</i><br />refresh_rate=90<br /><br /><i># List of audio files to play in the browser in case of problems. These files<br /># are assumed to be in the /var/www/nagios/media/ directory</i><br />host_unreachable_sound=hostdown.wav<br />host_down_sound=hostdown.wav<br />service_critical_sound=critical.wav<br />service_warning_sound=warning.wav<br />service_unknown_sound=warning.wav<br /><i>#normal_sound=noproblem.wav</i><br /><br /><i># HTML and URL target options</i><br />action_url_target=_blank<br />notes_url_target=_blank<br />escape_html_tags=1<br /><br /><i># Restrict users from changing the author name when submitting comments,<br /># acknowledgements and scheduled downtime from the web interface</i><br />lock_author_names=1<br /><br /><i># Splunk integration options</i><br />enable_splunk_integration=0<br />#splunk_url=http://127.0.0.1:8000/<br /></pre> </div> <h3><a id="nagios-4.2" name="nagios-4.2"></a>4.2 Apache configuration</h3> <p>The web interface holds particularly sensitive information about network and services and may even allow the execution of commands that directly affect the monitoring daemon. As a consequence, it is strongly recommended that you configure authentication for accessing the CGIs.</p> <p>User authentication files are managed with the <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=htpasswd&sektion=1">htpasswd(1)</a></tt> utility. Note that the first time you run this command, you must supply the "<tt>-c</tt>" option to create the password file:</p> <div class="code"> <pre># <kbd>htpasswd -c /var/www/users/nagios.passwd nagiosadmin</kbd><br />New password: <kbd><var>password</var></kbd><br />Re-type new password: <kbd><var>password</var></kbd><br />Adding password for user nagiosadmin<br /># <kbd>htpasswd /var/www/users/nagios.passwd danix@work</kbd><br />New password: <kbd><var>password</var></kbd><br />Re-type new password: <kbd><var>password</var></kbd><br />Adding password for user danix@work<br />#<br /></pre> </div> <p>An authenticated user whose username matches the short name of a contact definition is called an <dfn>authenticated contact</dfn> and is automatically granted access to information and commands for those hosts and services for which he is contact (please refer to the <a href="http://nagios.sourceforge.net/docs/3_0/cgiauth.html">documentation</a> for further details about authentication in the CGIs).</p> <p>Well, now that we have Apache requiring users to authenticate, we should also configure <acronym title="Secure Sockets Layer">SSL</acronym> to avoid sending passwords in clear text. Below are the <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=openssl&sektion=1">openssl(1)</a></tt> commands to create a self-signed certificate (a more detailed discussion about certificate management can be found <a href="http://www.modssl.org/docs/2.8/ssl_faq.html">here</a>).</p> <div class="code"> <pre># <kbd>openssl genrsa -des3 -out server.3des-key 1024</kbd><br />Generating RSA private key, 1024 bit long modulus<br />..............++++++<br />.++++++<br />e is 65537 (0x10001)<br />Enter pass phrase for server.3des-key: <kbd><var>passphrase</var></kbd><br />Verifying - Enter pass phrase for server.3des-key: <kbd><var>passphrase</var></kbd><br /># <kbd>openssl rsa -in server.3des-key -out server.key</kbd><br />Enter pass phrase for server.3des-key: <kbd><var>passphrase</var></kbd><br />writing RSA key<br /># <kbd>openssl req -new -key server.key -x509 -out server.crt -days 365</kbd><br />You are about to be asked to enter information that will be incorporated<br />into your certificate request.<br />What you are about to enter is what is called a Distinguished Name or a DN.<br />There are quite a few fields but you can leave some blank<br />For some fields there will be a default value,<br />If you enter '.', the field will be left blank.<br />-----<br />Country Name (2 letter code) []: <kbd>IT</kbd><br />State or Province Name (full name) []: <kbd><var>State</var></kbd><br />Locality Name (eg, city) []: <kbd><var>Locality</var></kbd><br />Organization Name (eg, company) []: <kbd>kernel-panic.it</kbd><br />Organizational Unit Name (eg, section) []: <kbd>Information Technology</kbd><br />Common Name (eg, fully qualified host name) []: <kbd>nagios.kernel-panic.it</kbd><br />Email Address []: <kbd>nagios@kernel-panic.it</kbd><br /># <kbd>chmod 600 server.key</kbd><br /># <kbd>rm server.3des-key</kbd><br /># <kbd>mv server.crt /etc/ssl/</kbd><br /># <kbd>mv server.key /etc/ssl/private/</kbd><br /></pre> </div> <p>The last step is configuring Apache to actually require authentication and encryption to access the Nagios interface by adding the following lines to the <tt>/var/www/conf/httpd.conf</tt> configuration file:</p> <div class="code"> <div>/var/www/conf/httpd.conf</div> <pre>ScriptAlias /cgi-bin/nagios "/var/www/cgi-bin/nagios"<br /><br /><directory><br /> SSLRequireSSL<br /><br /> Options ExecCGI<br /><br /> AuthName "Nagios Access"<br /> AuthType Basic<br /> AuthUserFile /users/nagios.passwd<br /> Require valid-user<br /><br /> Order deny,allow<br /> Deny from all<br /> <i># Authorized clients</i><br /> Allow from 127.0.0.1 172.16.0.13<br /></directory><br /><br />Alias /nagios "/var/www/nagios"<br /><br /><directory><br /> SSLRequireSSL<br /><br /> Options None<br /> AllowOverride None<br /><br /> AuthName "Nagios Access"<br /> AuthType Basic<br /> AuthUserFile /users/nagios.passwd<br /> Require valid-user<br /><br /> Order deny,allow<br /> Deny from all<br /> <i># Authorized clients</i><br /> Allow from 127.0.0.1 172.16.0.13<br /></directory><br /></pre> </div> <h3><a id="nagios-4.3" name="nagios-4.3"></a>4.3 Running Nagios</h3> <p>Well, it looks like we're done with the configuration for now! Then we can make Nagios evaluate our hard work by invoking it with the "<tt>-v</tt>" option:</p> <div class="code"> <pre># <kbd>/usr/local/sbin/nagios -v /var/www/etc/nagios/nagios.cfg</kbd><br /><br />Nagios 3.0.3<br />Copyright (c) 1999-2008 Ethan Galstad (http://www.nagios.org)<br />Last Modified: 06-25-2008<br />License: GPL<br /><br />Reading configuration data...<br /><br />Running pre-flight check on configuration data...<br /><br />[...]<br /><br />Total Warnings: 0<br />Total Errors: 0<br /><br />Things look okay - No serious problems were detected during the pre-flight check<br />#<br /></pre> </div> <p>If no errors were detected, then the long-awaited moment has arrived: we are ready to start Nagios! Though not before having created the directory for the lock file (<em>Note</em>: if you haven't rebooted since installing the Nagios packages, the <tt>/var/run/nagios/</tt> directory should already exist).</p> <div class="code"> <pre># <kbd>apachectl startssl</kbd><br />/usr/sbin/apachectl startssl: httpd started<br /># <kbd>install -d -o _nagios /var/run/nagios</kbd><br /># <kbd>/usr/local/sbin/nagios -d /var/www/etc/nagios/nagios.cfg</kbd><br /></pre> </div> <p>You can check if everything is working fine by connecting to the web interface (<tt>https://<var>your.server.here</var>/nagios/</tt>) or taking a look at the logs (<tt>/var/www/var/log/nagios/nagios.log</tt>).</p> <p>To finish up, we have to configure the system to start both Apache and Nagios at boot time, by setting the <tt>httpd_flags</tt> variable in the <tt>/etc/rc.conf.local</tt> file:</p> <div class="code"> <div>/etc/rc.conf.local</div> <pre>httpd_flags="-DSSL"<br /></pre> </div> <p>and by adding the following lines to the <tt>/etc/rc.local</tt> file:</p> <div>/etc/rc.local</div> <pre>if [ -x /usr/local/sbin/nagios ]; then<br /> install -d -o _nagios /var/run/nagios<br /> echo -n ' nagios'<br /> /usr/local/sbin/nagios -d /var/www/etc/nagios/nagios.cfg<br />fi<br /><br /><br /><br /><br /><br /></pre><h2>5. Nagios addons</h2> <p>One of Nagios' key features is its extensibility; new functionality can be easily added thanks to its plugin-based architecture, the external command interface and the <a href="http://httpd.apache.org/">Apache</a> web server. In this chapter, we will take a look at a few common issues that can be addressed with some of the most popular <a href="http://www.nagiosexchange.org/">addons</a> for Nagios.</p> <h3><a id="nagios-5.1" name="nagios-5.1"></a>5.1 NRPE</h3> <p>Suppose you want Nagios to monitor local services on remote hosts, such as disk space usage, system load or the number of users currently logged in. These are not network services, so they can't be directly checked out with standard plugins: what we would need is some kind of <dfn>agent</dfn> to install on remote systems and that Nagios could periodically query for the status of local services.</p> <p>Well, that's exactly what the <a href="http://www.nagiosexchange.org/cgi-bin/page.cgi?g=Detailed%2F1556.html;d=1"><dfn>Nagios Remote Plugin Executor</dfn></a> (NRPE) does: it <q>allows you to execute local plugins on remote hosts</q>! It is made up of two components:</p> <ul><li>an agent, running (either standalone or under <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8">inetd(8)</a></tt>) on the monitored host, which waits for incoming connections, executes the requested checks and returns the status of the local services;</li><li>a plugin, "<tt>check_nrpe</tt>", used by Nagios to query the remote agents.</li></ul> <p>Both the agent and the plugin are available from the following package:</p> <ul><li>nrpe-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li></ul> <p>In addition, the Nagios plugins package will be installed on the monitored host as a dependency: this will allow the NRPE agent to take advantage of the standard Nagios plugins to perform local checks. The package installation automatically creates the <tt>_nrpe</tt> user and group that the daemon will run as and copy a sample <tt>nrpe.cfg</tt> configuration file in <tt>/etc/</tt>:</p> <div class="code"> <div>/etc/nrpe.cfg</div> <pre><i># Path to the pid file (ignored if running under inetd)</i><br />pid_file=/var/run/nrpe.pid<br /><br /><i># Address to bind to, to avoid binding on all interfaces (ignored if running<br /># under inetd)</i><br />server_address=172.16.0.170<br /><i># Port to wait connections on (ignored if running under inetd)</i><br />server_port=5666<br /><br /><i># User and group the NRPE daemon should run as (ignored if running under inetd)</i><br />nrpe_user=_nrpe<br />nrpe_group=_nrpe<br /><br /><i># Comma-delimited list of IP addresses or hostnames that are allowed to connect<br /># to the NRPE daemon (ignored if running under inetd)</i><br />allowed_hosts=127.0.0.1,172.16.0.164<br /><br /><i># Don't allow clients to specify arguments to commands that are executed</i><br />dont_blame_nrpe=0<br /><br /><i># Uncomment the following option to prefix all commands with a specific string<br />#command_prefix=/usr/bin/sudo</i><br /><br /><i># Don't log debugging messages to the syslog facility</i><br />debug=0<br /><br /><i># Maximum length (in seconds) of executed plugins</i><br />command_timeout=60<br /><br /><i># Command definitions are in the form<br />#<br /># command[<command_name>]=<command_line><br />#<br /># Thus, when the NRPE daemon receives a request to execute the command<br /># 'command_name', it will run the *local* script specified by 'command_line'.<br /># Note: macros are NOT allowed within command definitions</command_line></command_name></i><br />command[check_users]=/usr/local/libexec/nagios/check_users -w 5 -c 10<br />command[check_load]=/usr/local/libexec/nagios/check_load -w 15,10,5 -c 30,25,20<br />command[check_disk1]=/usr/local/libexec/nagios/check_disk -w 20 -c 10 -p /dev/wd0a<br />command[check_total_procs]=/usr/local/libexec/nagios/check_procs -w 150 -c 200<br /></pre> </div> <p>To run NRPE as a standalone daemon, simply type:</p> <div class="code"> <pre># <kbd>/usr/local/sbin/nrpe -c /etc/nrpe.cfg -d</kbd><br /></pre> </div> <p>and add the following lines to <tt>/etc/rc.local</tt> to start it automatically after reboot:</p> <div class="code"> <div>/etc/rc.local/</div> <pre>if [ -x /usr/local/sbin/nrpe ]; then<br /> echo -n ' nrpe'<br /> /usr/local/sbin/nrpe -c /etc/nrpe.cfg -d<br />fi<br /></pre> </div> <p><em>Alternatively</em>, you can run NRPE under <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8">inetd(8)</a></tt> by adding the following line in <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd.conf&sektion=8">/etc/inetd.conf(8)</a></tt>:</p> <div class="code"> <div>/etc/inetd.conf</div> <pre>nrpe stream tcp wait _nrpe:_nrpe /usr/local/sbin/nrpe nrpe -c /etc/nrpe.cfg -i<br /></pre> </div> <p>and by adding the <tt>nrpe</tt> service in <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=services&sektion=5">/etc/services(5)</a></tt>:</p> <div class="code"> <div>/etc/services</div> <pre>nrpe 5666/tcp <i># Nagios Remote Plugin Executor</i><br /></pre> </div> <p>and then send the <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8">inetd(8)</a></tt> daemon the hangup signal, instructing it to re-read its configuration:</p> <div class="code"> <pre># <kbd>pkill -HUP inetd</kbd><br /></pre> </div> <p>Now, on the Nagios server, you can perform checks using NRPE simply by defining commands such as the following (only make sure that the command name passed to the "<tt>-c</tt>" option has a corresponding command definition in the <tt>nrpe.cfg</tt> file on the remote host!):</p> <div class="code"> <div>/var/www/etc/nagios/commands.cfg</div> <pre>define command {<br /> command_name check-disk1-nrpe<br /> command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c check_disk1<br />}<br /></pre> </div> <h3><a id="nagios-5.2" name="nagios-5.2"></a>5.2 NSCA</h3> <p>Now suppose you want to monitor the correct execution of a process on a remote host, like a scheduled backup or a crontab job. This is still a "local" service, but, unlike disk space usage or system load, it would probably sound more logical to make it the responsibility of the job itself to notify Nagios of its exit status. That's the perfect job for the <dfn>Nagios Service Check Acceptor</dfn> (NSCA), which is a daemon program, meant to run on the Nagios server, <q>designed to accept passive service check results from clients</q>.</p> <p>NSCA is similar to NRPE in that it is made up of a daemon process and a client application, but now the roles are inverted: the daemon process runs on the Nagios server while remote hosts use the <tt>send_nsca</tt> utility to communicate their status to the daemon. NSCA then forwards the check results to Nagios through the external command interface (so make sure you have enabled external commands in the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.1">main configuration file</a>).</p> <h4><a id="nagios-5.2.1" name="nagios-5.2.1"></a>5.2.1 Server configuration</h4> <p>NSCA can run either as a standalone daemon or under <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8">inetd(8)</a></tt>. To install the server component we need to add the following packages on the Nagios server:</p> <ul><li>pcre-<var>x</var>.<var>x</var>.tgz</li><li>glib2-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>mhash-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>libmcrypt-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>nsca-<var>x</var>.<var>x</var>.tgz</li></ul> <p>Next, we need to edit the <tt>/etc/nsca.cfg</tt> configuration file:</p> <div class="code"> <div>/etc/nsca.cfg</div> <pre><i># Path to the pid file (ignored if running under inetd)</i><br />pid_file=/var/run/nrpe.pid<br /><br /><i># Address to bind to (optional)</i><br />server_address=172.16.0.164<br /><i># Port to wait connections on</i><br />server_port=5667<br /><br /><i># User and group the NSCA daemon should run as (ignored if running under inetd)</i><br />nsca_user=_nagios<br />nsca_group=_nagios<br /><br /><i># <a href="http://www.openbsd.org/cgi-bin/man.cgi?query=chroot&sektion=2">chroot(2)</a> directory for the NSCA daemon</i><br />nsca_chroot=/var/www/var/nagios/rw<br /><br /><i># Don't log debugging messages to the syslog facility</i><br />debug=0<br /><br /><i># Path to the command file (relative to the chroot directory)</i><br />command_file=nagios.cmd<br /><i># File where to dump service check results if the command file does not exist</i><br />alternate_dump_file=nsca.dump<br /><br /><i># Do not aggregate writes to the external command file</i><br />aggregate_writes=0<br /><i># Open the external command file in write mode</i><br />append_to_file=0<br /><br /><i># Maximum packet age (in seconds)</i><br />max_packet_age=30<br /><br /><i># Password to use to decrypt incoming packets</i><br />password=password<br /><i># Decryption method (16 = RIJNDAEL-256). It must match the encryption method<br /># used by the client</i><br />decryption_method=16<br /></pre> </div> <p>You should set restrictive permissions (600) on the configuration file in order to keep the decryption password protected. To run NSCA as a standalone daemon, simply type:</p> <div class="code"> <pre># <kbd>/usr/local/sbin/nsca -c /etc/nsca.cfg</kbd><br /></pre> </div> <p>and add the following lines to <tt>/etc/rc.local</tt> to start it automatically after reboot:</p> <div class="code"> <div>/etc/rc.local</div> <pre>if [ -x /usr/local/sbin/nsca ]; then<br /> echo -n ' nsca'<br /> /usr/local/sbin/nsca -c /etc/nsca.cfg<br />fi<br /></pre> </div> <p><em>Alternatively</em>, you can run it under <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8">inetd(8)</a></tt> by adding the following line in <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd.conf&sektion=8">/etc/inetd.conf(8)</a></tt>:</p> <div class="code"> <div>/etc/inetd.conf</div> <pre>nsca stream tcp wait _nagios:_nagios /usr/local/sbin/nsca nsca -c /etc/nsca.cfg --inetd<br /></pre> </div> <p>and by adding the <tt>nsca</tt> service in <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=services&sektion=5">/etc/services(5)</a></tt>:</p> <div class="code"> <div>/etc/services</div> <pre>nsca 5667/tcp <i># Nagios Service Check Acceptor</i><br /></pre> </div> <p>and then send the <tt><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=inetd&sektion=8">inetd(8)</a></tt> daemon the hangup signal, instructing it to re-read its configuration:</p> <div class="code"> <pre># <kbd>pkill -HUP inetd</kbd><br /></pre> </div> <h4><a id="nagios-5.2.2" name="nagios-5.2.2"></a>5.2.2 Client configuration</h4> <p>On the client side, we need to install the following packages:</p> <ul><li>mhash-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>libmcrypt-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>nsca-client-<var>x</var>.<var>x</var>.tgz</li></ul> <p>and edit the encryption parameters in the <tt>/etc/send_nsca.cfg</tt> configuration file:</p> <div class="code"> <div>/etc/send_nsca.cfg</div> <pre><i># Password to use to encrypt outgoing packets</i><br />password=password<br /><i># Encryption method (16 = RIJNDAEL-256)</i><br />encryption_method=16<br /></pre> </div> <p>The <tt>send_nsca</tt> utility reads data from standard input and expects, for service checks, a tab separated sequence of <var>host name</var>, <var>service description</var> (i.e. the value of the <tt>service_description</tt> directive in the service definition), <var>return code</var> and <var>output</var>; e.g.:</p> <div class="code"> <pre>echo "www1\tbackup\t0\tBackup completed successfully" | /usr/local/libexec/nagios/send_nsca -H nagios.kernel-panic.it<br /></pre> </div> <p>and, for host checks, a tab separated sequence of <var>host name</var>, <var>return code</var> and <var>output</var>; e.g.:</p> <div class="code"> <pre>echo "router1\t2\tRouter #1 is down" | /usr/local/libexec/nagios/send_nsca -H nagios.kernel-panic.it<br /></pre> </div> <p>You can override the default delimiter (tab) with <tt>send_nsca</tt>'s "<tt>-d</tt>" option. Now, if everything is working fine, each message received by the NSCA daemon should produce a line like the following in the Nagios log file:</p> <div class="code"> <div>/var/www/var/log/nagios/nagios.log</div> <pre>[1167325538] EXTERNAL COMMAND: PROCESS_SERVICE_CHECK_RESULT;www1;backup;0;Backup completed successfully<br /></pre> </div> <h3><a id="nagios-5.3" name="nagios-5.3"></a>5.3 NagVis and NDO</h3> <p><a href="http://www.nagvis.org/doku.php">NagVis</a> is a visualization addon for Nagios; it can be used to give users a <a href="http://www.nagvis.org/doku.php?id=screenshots">graphical view</a> of Nagios data. It requires the installation of <a href="http://www.php.net/">PHP</a> and a few libraries:</p> <ul><li>libxml-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>t1lib-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>jpeg-<var>x</var>.tgz</li><li>png-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>php5-core-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>php5-gd-<var>x</var>.<var>x</var>.<var>x</var>-no_x11.tgz</li><li>mysql-client-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li><li>php5-mysql-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li></ul> <p>Apache is already up and running, so we only need to enable the php modules we have just installed:</p> <div class="code"> <pre># <kbd>ln -s /var/www/conf/modules.sample/php5.conf /var/www/conf/modules</kbd><br /># <kbd>ln -fs /var/www/conf/php5.sample/gd.ini /var/www/conf/php5/gd.ini</kbd><br /># <kbd>ln -fs /var/www/conf/php5.sample/mysql.ini /var/www/conf/php5/mysql.ini</kbd><br /></pre> </div> <p>uncomment the following line in <tt>/var/www/conf/httpd.conf</tt>:</p> <div class="code"> <div>/var/www/conf/httpd.conf</div> <pre>AddType application/x-httpd-php .php<br /></pre> </div> <p>and restart Apache:</p> <div class="code"> <pre># <kbd>apachectl restart</kbd><br />/usr/sbin/apachectl restart: httpd restarted<br /></pre> </div> <h4><a id="nagios-5.3.1" name="nagios-5.3.1"></a>5.3.1 Installing NDO and MySQL</h4> <p>Prior to version 1.0, NagVis was able to pull data from Nagios directly from its web interface; now this is not supported anymore and NagVis expects monitoring data to be stored in a MySQL database, thus requiring the intallation of the <dfn>Nagios Data Output Utils</dfn> (NDOUTILS) addon.</p> <p>The NDOUTILS addon <q>allows you to export current and historical data from one or more Nagios instances to a MySQL database</q>, thus providing the interface between Nagios and MySQL. This addon consists of several parts, but we will need only two of them:</p> <ul><li>the NDOMOD event broker module, which is loaded by Nagios at startup and dumps all events and data from Nagios to a Unix or TCP socket;</li><li>the NDO2DB daemon, which is a standalone daemon and reads the output produced by the NDOMOD module through the Unix or TCP socket and dumps it into the database.</li></ul> <p>First off, we need to install MySQL; the following is the list of the required packages:</p> <ul><li>p5-Net-Daemon-<var>x</var>.<var>x</var>.tgz</li><li>p5-PlRPC-<var>x</var>.<var>x</var>.tgz</li><li>p5-DBI-<var>x</var>.<var>x</var>.tgz</li><li>p5-DBD-mysql-<var>x</var>.<var>x</var>.tgz</li><li>mysql-server-<var>x</var>.<var>x</var>.<var>x</var>.tgz</li></ul> <p>Next, we need to <a href="http://sourceforge.net/project/showfiles.php?group_id=26589">download</a>, extract and compile the NDOUTILS tarball:</p> <div class="code"> <pre># <kbd>tar -zxvf ndoutils-<var>x</var>.<var>x</var>.<var>x</var>.tar.gz</kbd><br />[ ... ]<br /># <kbd>cd ndoutils-<var>x</var>.<var>x</var>.<var>x</var></kbd><br /># <kbd>./configure --disable-pgsql --enable-mysql --with-mysql-lib=/usr/local/lib \<br />> --with-mysql-inc=/usr/local/include</kbd><br />[ ... ]<br /># <kbd>make</kbd><br /></pre> </div> <p><em>Note</em>: if <tt>make</tt> fails to compile the <tt>dbhandlers.c</tt> file, try installing <a href="http://www.kernel-panic.it/openbsd/nagios/ndo-openbsd.patch">this patch</a> (applies to version 1.4b7) by running the following command from outside the ndoutils source tree:</p> <div class="code"> <pre># <kbd>patch -p0 <><br /></kbd></pre> </div> <p>Now we can start MySQL, assign a password to the root account and create the appropriate database and user. The database creation script can be found in the <tt>db/</tt> directory of the extracted tarball.</p> <div class="code"> <pre># <kbd>cp /usr/local/share/mysql/my-medium.cnf /etc/my.cnf</kbd><br /># <kbd>/usr/local/bin/mysql_install_db</kbd><br />[ ... ]<br /># <kbd>mysqld_safe &</kbd><br />Starting mysqld daemon with databases from /var/mysql<br /># <kbd>/usr/local/bin/mysql_secure_installation</kbd><br />[ ... ]<br />Enter current password for root (enter for none): <kbd><i><enter></enter></i></kbd><br />[ ... ]<br />Set root password? [Y/n] <kbd>Y</kbd><br />New password: <kbd><i>root</i></kbd><br />Re-enter new password: <kbd><i>root</i></kbd><br />[ ... ]<br />Remove anonymous users? [Y/n] <kbd>Y</kbd><br />[ ... ]<br />Disallow root login remotely? [Y/n] <kbd>Y</kbd><br />[ ... ]<br />Remove test database and access to it? [Y/n] <kbd>Y</kbd><br />[ ... ]<br />Reload privilege tables now? [Y/n] <kbd>Y</kbd><br />[ ... ]<br /># <kbd>mysql -u root -p</kbd><br />password: <kbd><i>root</i></kbd><br />Welcome to the MySQL monitor. Commands end with ; or \g.<br />Server version: 5.0.51a-log OpenBSD port: mysql-server-5.0.51a<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql> <kbd>create database nagios;</kbd><br />Query OK, 1 row affected (0.02 sec)<br /><br />mysql> <kbd>use nagios;</kbd><br />Database changed<br />mysql> <kbd>\. db/mysql.sql</kbd><br />[...]<br />mysql> <kbd>GRANT SELECT, INSERT, UPDATE, DELETE ON nagios.* TO 'ndouser'@'localhost' IDENTIFIED BY 'ndopasswd';</kbd><br />mysql> <kbd>\q</kbd><br /></pre> </div> <p>Now we need to manually copy the binaries and configuration files:</p> <div class="code"> <pre># <kbd>cp src/ndomod-3x.o /usr/local/libexec/nagios/ndomod.o</kbd><br /># <kbd>cp config/ndomod.cfg /var/www/etc/nagios/</kbd><br /># <kbd>cp src/ndo2db-3x /usr/local/sbin/ndo2db</kbd><br /># <kbd>cp config/ndo2db.cfg /var/www/etc/nagios/</kbd><br /></pre> </div> <p>and edit the NDOMOD configuration file:</p> <div class="code"> <div>/var/www/etc/nagios/ndomod.cfg</div> <pre>instance_name=default<br />output_type=unixsocket<br />output=/var/nagios/rw/ndo.sock<br />tcp_port=5668<br /><br />output_buffer_items=5000<br />buffer_file=/var/nagios/rw/ndomod.tmp<br /><br />file_rotation_interval=14400<br />file_rotation_timeout=60<br /><br />reconnect_interval=15<br />reconnect_warning_interval=15<br />data_processing_options=-1<br />config_output_options=3<br /></pre> </div> <p>and the NDO2DB configuration file:</p> <div class="code"> <div>/var/www/etc/nagios/ndo2db.cfg</div> <pre>ndo2db_user=_nagios<br />ndo2db_group=_nagios<br /><br />socket_type=unix<br />socket_name=/var/www/var/nagios/rw/ndo.sock<br />tcp_port=5668<br /><br />db_servertype=mysql<br />db_host=localhost<br />db_port=3306<br />db_name=nagios<br />db_prefix=nagios_<br />db_user=ndouser<br />db_pass=ndopasswd<br /><br />max_timedevents_age=1440<br />max_systemcommands_age=10080<br />max_servicechecks_age=10080<br />max_hostchecks_age=10080<br />max_eventhandlers_age=44640<br /><br />debug_level=0<br />debug_verbosity=1<br />debug_file=/var/www/var/log/nagios/ndo2db.debug<br />max_debug_file_size=1000000<br /></pre> </div> <p>Then we have to specify the event broker module that Nagios must load at startup, by adding the following line to the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios2.html#nagios-2.2.1">main configuration file</a>:</p> <div class="code"> <div>/var/www/etc/nagios/nagios.cfg</div> <pre>broker_module=/usr/local/libexec/nagios/ndomod.o config_file=/var/www/etc/nagios/ndomod.cfg<br /></pre> </div> <p>and, finally, we can start the NDO2DB daemon and restart Nagios:</p> <div class="code"> <pre># <kbd>/usr/local/sbin/ndo2db -c /var/www/etc/nagios/ndo2db.cfg</kbd><br /># <kbd>chmod 770 /var/www/var/nagios/rw/ndo.sock</kbd><br /># <kbd>pkill nagios</kbd><br /># <kbd>nagios -d /var/www/etc/nagios/nagios.cfg</kbd><br /></pre> </div> <p>Add the following lines to <tt>/etc/rc.local</tt> to start the NDO2DB daemon on boot:</p> <div class="code"> <div>/etc/rc.local</div> <pre>if [ -x /usr/local/sbin/ndo2db ]; then<br /> echo -n ' ndo2db'<br /> /usr/local/sbin/ndo2db -c /var/www/etc/nagios/ndo2db.cfg<br /> chmod 770 /var/www/var/nagios/rw/ndo.sock<br />fi<br /></pre> </div> <h4><a id="nagios-5.3.2" name="nagios-5.3.2"></a>5.3.2 Configuring NagVis</h4> <p>Now that we have installed all the necessary prerequisites, we can <a href="http://www.nagvis.org/downloads">download</a> and extract the NagVis tarball:</p> <div class="code"> <pre># <kbd>cd /var/www/nagios/</kbd><br /># <kbd>tar -zxvf nagvis-<var>x</var>.<var>x</var>.<var>x</var>.tar.gz</kbd><br />[ ... ]<br /># <kbd>mv nagvis-<var>x</var>.<var>x</var>.<var>x</var> nagvis</kbd><br /># <kbd>chown -R www /var/www/nagios/nagvis/{etc,var}</kbd><br /></pre> </div> <p>Below is a sample NagVis configuration file; please refer to the <a href="http://docs.nagvis.org/1.3/en_US/index.html">documentation</a> for a detailed description of each parameter:</p> <div class="code"> <div>/var/www/nagios/nagvis/etc/nagvis.ini.php</div> <pre><i>; </i><br /><br />[global]<br />language = "english"<br />displayheader = 1<br />refreshtime = 60<br />dateformat = "Y-m-d H:i:s"<br /><br />[defaults]<br />backend = "ndomy_1"<br /><i>; Default icons' size (icons can be found in<br />; /var/www/nagios/nagvis/images/iconsets)</i><br />icons = "std_medium"<br />recognizeservices = 1<br />onlyhardstates = 0<br />backgroundcolor = "#fff"<br />headertemplate = "default"<br />hovertemplate = "default"<br />hoverdelay = 0<br />showinlists = 1<br /><i>; Use gdlibs (if set to 0 lines will not work, all other types should work fine)</i><br />usegdlibs = 1<br />urltarget = "_self"<br /><br />[wui]<br />autoupdatefreq = 25<br />maplocktime = 5<br />allowedforconfig = nagiosadmin<br /><br />[paths]<br />base = "/nagios/nagvis/"<br />htmlbase = "/nagios/nagvis"<br />htmlcgi = "/cgi-bin/nagios"<br /><br />[backend_ndomy_1]<br />backendtype = "ndomy"<br />dbhost = "127.0.0.1"<br />dbport = 3306<br />dbname = "nagios"<br />dbuser = "ndouser"<br />dbpass = "ndopasswd"<br />dbprefix = "nagios_"<br />dbinstancename = "default"<br />maxtimewithoutupdate = 180<br />htmlcgi = "/cgi-bin/nagios"<br /><br /><i>; In this example, the browser switches between the 'dmz' and 'lan' maps every<br />; 15 seconds. The rotation is enabled by specifying the URL:<br />; https://your.nagios.server/nagios/nagvis/index.php?rotation=kp</i><br />[rotation_kp]<br />maps = "dmz,lan"<br />interval = 15<br /><br />[automap]<br />showinlists=0<br /></pre> </div> <h4><a id="nagios-5.3.3" name="nagios-5.3.3"></a>5.3.3 Maps definition</h4> <p>Now we have to create the images for NagVis to use as the background for each map and put them in the <tt> /var/www/nagios/nagvis/images/maps/</tt> directory. You can find a few examples <a href="http://www.nagvis.org/screenshots">here</a>.</p> <p>Once the map images are ready, we can tell NagVis where to place objects on the map by creating and editing the maps configuration files. Each map must have a corresponding configuration file (in <tt>/var/www/nagios/nagvis/etc/maps/</tt>) with the same name, plus the "<tt>.cfg</tt>" extension. Below is a sample map configuration file; syntax is rather simple, so you can easily tweak it to include your own hosts and services (please refer to the <a href="http://docs.nagvis.org/1.3/en_US/index.html">documentation</a> for further details).</p> <div class="code"> <div>/var/www/nagios/nagvis/etc/maps/dmz.cfg</div> <pre><i># The 'global' statement sets some default values that will be inherited by all<br /># other objects</i><br />define global {<br /><i># List of users allowed to view this map</i><br /> allowed_user=nagiosadmin,operator<br /><i># List of users allowed to modify this map via the web interface</i><br /> allowed_for_config=nagiosadmin<br /><i># Defaul iconset (if omitted, it is inherited from the <a href="http://www.kernel-panic.it/openbsd/nagios/nagios5.html#nagios-5.3.2">main configuration file</a>)</i><br /> iconset=std_medium<br /><i># Background image</i><br /> map_image=dmz.png<br />}<br /><br /><i># Display the status of our 'www1' web server</i><br />define host {<br /> host_name=www1<br /><i># Coordinates of the host on the map</i><br /> x=268<br /> y=166<br /><i># Set this to '1' if you want the host status to also include the status<br /># of its services</i><br /> recognize_services=0<br />}<br /><br /><i># Display the status of the 'WWW' service on the 'www1' web server</i><br />define service {<br /> host_name=www1<br /> service_description=WWW<br /> x=588<br /> y=165<br /><i># As you can see, 'global' options can be overridden in subsequent objects</i><br /> iconset=std_small<br />}<br /><br /><i># Display the worsest state of hosts in the 'WWW' hostgroup</i><br />define hostgroup {<br /> hostgroup_name=WWW<br /> x=298<br /> y=363<br /> recognize_services=1<br />}<br /><br /><i># Display the worsest state of services in the 'www-services' servicegroup</i><br />define servicegroup {<br /> servicegroup_name=www-services<br /> x=609<br /> y=363<br />}<br /><br /><i># Display the worsest state of objects represented in another NagVis map</i><br />define map {<br /> map_name=lan<br /> x=406<br /> y=323<br />}<br /><br /><i># Draw a textfield on the map</i><br />define textbox {<br /><i># Text may include HTML</i><br /> text="This is the DMZ network"<br /> x=490<br /> y=394<br /> w=117<br />}<br /></pre> </div> <p>To allow the web interface to modify NagVis' configuration, make sure that all configuration files belong to, and are writable by, the <tt>www</tt> user.</p> <div class="code"> <pre># <kbd>chown www /var/www/nagios/nagvis/etc/maps/*.cfg</kbd><br /># <kbd>chmod 644 /var/www/nagios/nagvis/etc/maps/*.cfg</kbd><br /></pre> </div><pre><br /></pre><h2>6. Writing your own Nagios plugins</h2> <p>Plugins are executable files run by Nagios to determine the status of a host or service. By default, Nagios comes with a very rich set of official plugins that should cover most people's needs; in addition, you can find lots of contributed plugins on the <a href="http://www.nagiosexchange.org/Check_Plugins.21.0.html">Nagios Exchange website</a>, some of which are also available via OpenBSD's packages and ports system.</p> <p>However, despite the abundance of plugins, there may be occasions in which no existing plugin is suitable for monitoring a particular service, thus forcing you to write a fully custom plugin, tailored to your exact needs. Luckily, this is a very simple task!</p> <p>Nagios doesn't bind you to a specific programming language: plugins may be either compiled C programs or interpreted scripts, in Perl, shell or Python. Nagios doesn't mess with the internals of plugins; however, it asks developers to follow a few basic <a href="http://nagiosplug.sourceforge.net/developer-guidelines.html">guidelines</a>, just for standard's sake.</p> <h3><a id="nagios-6.1" name="nagios-6.1"></a>6.1 Command line options</h3> <p>A plugin's command line must follow some specific requirements:</p> <ul><li>positional arguments are strongly discouraged;</li><li>all plugins should provide a "<tt>-V</tt>" command-line option (and "<tt>--version</tt>" if long options are enabled) to display the plugin's revision number;</li><li>the "<tt>-?</tt>" option, as well as any incorrect option, displays a short usage statement that should fit on a standard 80x25 terminal;</li><li>the "<tt>-h</tt>", or "<tt>--help</tt>", option displays detailed help information;</li><li>the "<tt>-v</tt>", or "<tt>--verbose</tt>", option adjusts the verbosity level; multiple "<tt>-v</tt>" options (up to 3) should increase the verbosity level, as described in the <a href="http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN40">official guidelines</a>;</li><li>There are a few other reserved options that should not be used for other purposes: <ul><li>"<tt>-t</tt>" or "<tt>--timeout</tt>" (plugin timeout);</li><li>"<tt>-w</tt>" or "<tt>--warning</tt>" (warning threshold);</li><li>"<tt>-c</tt>" or "<tt>--critical</tt>" (critical threshold);</li><li>"<tt>-H</tt>" or "<tt>--hostname</tt>" (name of the host to check).</li></ul> </li></ul> <h3><a id="nagios-6.2" name="nagios-6.2"></a>6.2 Plugin return codes</h3> <p>Nagios determines the status of a host or service based on the return code of the plugin. Valid return codes are:</p> <table class="retcodes"> <tbody><tr> <th>Numeric value</th> <th>Service/Host status</th> <th>Service Status description</th> <th>Host status description</th> </tr> <tr> <td>0</td> <td>Ok/Up</td> <td class="left">The plugin was able to check the service and it seemed to work correctly</td> <td class="left">The host is up and replied in acceptable time</td> </tr> <tr> <td>1</td> <td>Warning</td> <td class="left">The plugin was able to check the service, but it didn't seem to work correctly or it exceeded some "warning" threshold</td> <td class="left">The host is up, but some "warning" threshold was exceeded</td> </tr> <tr> <td>2</td> <td>Critical/Down</td> <td class="left">The service was not running or it exceeded some "critical" threshold</td> <td class="left">The host is down or some "critical" threshold was exceeded</td> </tr> <tr> <td>3</td> <td>Unknown</td> <td class="left">Invalid command line arguments were supplied or an internal error occurred</td> <td class="left">Invalid command line arguments were supplied or an internal error occurred</td> </tr> </tbody></table> <p>The <dfn>warning</dfn> and <dfn>critical</dfn> thresholds are usually set via command line options (see <a href="http://www.kernel-panic.it/openbsd/nagios/nagios6.html#nagios-6.1">above</a>).</p> <h3><a id="nagios-6.3" name="nagios-6.3"></a>6.3 A sample plugin script</h3> <p>Just a couple of notes before moving to a practical example:</p> <ul><li>plugins can access <a href="http://nagios.sourceforge.net/docs/2_0/macros.html">macros</a> as environment variables; such variables have the same name as the corresponding macros, with "<tt>NAGIOS_</tt>" prepended. For instance, the "<tt>$HOSTNAME$</tt>" macro will be accessible through the "<tt>NAGIOS_HOSTNAME</tt>" environment variable;</li><li>always specify the full path of any system commands run from your plugins.</li></ul> <p>Well, so let's see, as an example, what a plugin to monitor the amount of free memory on the local machine could look like:</p> <div class="code"> <div>/usr/local/libexec/nagios/check_free_mem.sh</div> <pre>#!/bin/ksh<br /><br /><i>################################################################################<br /># Sample Nagios plugin to monitor free memory on the local machine #<br /># Author: Daniele Mazzocchio (http://www.kernel-panic.it/) #<br />################################################################################</i><br /><br />VERSION="Version 1.0"<br />AUTHOR="(c) 2007-2008 Daniele Mazzocchio (danix@kernel-panic.it)"<br /><br />PROGNAME=`/usr/bin/basename $0`<br /><br /><i># Constants</i><br />BYTES_IN_MB=$(( 1024 * 1024 ))<br />KB_IN_MB=1024<br /><br /><i># Exit codes</i><br />STATE_OK=0<br />STATE_WARNING=1<br />STATE_CRITICAL=2<br />STATE_UNKNOWN=3<br /><br /><i># Helper functions #############################################################</i><br /><br />function print_revision {<br /> <i># Print the revision number</i><br /> echo "$PROGNAME - $VERSION"<br />}<br /><br />function print_usage {<br /> <i># Print a short usage statement</i><br /> echo "Usage: $PROGNAME [-v] -w <limit> -c <limit>"<br />}<br /><br />function print_help {<br /> <i># Print detailed help information</i><br /> print_revision<br /> echo "$AUTHOR\n\nCheck free memory on local machine\n"<br /> print_usage<br /><br /> /bin/cat <<__EOT<br /><br />Options:<br />-h<br /> Print detailed help screen<br />-V<br /> Print version information<br /><br />-w INTEGER<br /> Exit with WARNING status if less than INTEGER MB of memory are free<br />-w PERCENT%<br /> Exit with WARNING status if less than PERCENT of memory is free<br />-c INTEGER<br /> Exit with CRITICAL status if less than INTEGER MB of memory are free<br />-c PERCENT%<br /> Exit with CRITICAL status if less than PERCENT of memory is free<br />-v<br /> Verbose output<br />__EOT<br />}<br /><br /><i># Main #########################################################################</i><br /><br /><i># Total memory size (in MB)</i><br />tot_mem=$(( `/sbin/sysctl -n hw.physmem` / BYTES_IN_MB))<br /><i># Free memory size (in MB)</i><br />free_mem=$(( `/usr/bin/vmstat | /usr/bin/tail -1 | /usr/bin/awk '{ print $5 }'` / KB_IN_MB ))<br /><i># Free memory size (in percentage)</i><br />free_mem_perc=$(( free_mem * 100 / tot_mem ))<br /><br /><i># Verbosity level</i><br />verbosity=0<br /><i># Warning threshold</i><br />thresh_warn=<br /><i># Critical threshold</i><br />thresh_crit=<br /><br /><i># Parse command line options</i><br />while [ "$1" ]; do<br /> case "$1" in<br /> -h | --help)<br /> print_help<br /> exit $STATE_OK<br /> ;;<br /> -V | --version)<br /> print_revision<br /> exit $STATE_OK<br /> ;;<br /> -v | --verbose)<br /> : $(( verbosity++ ))<br /> shift<br /> ;;<br /> -w | --warning | -c | --critical)<br /> if [[ -z "$2" || "$2" = -* ]]; then<br /> <i># Threshold not provided</i><br /> echo "$PROGNAME: Option '$1' requires an argument"<br /> print_usage<br /> exit $STATE_UNKNOWN<br /> elif [[ "$2" = +([0-9]) ]]; then<br /> <i># Threshold is a number (MB)</i><br /> thresh=$2<br /> elif [[ "$2" = +([0-9])% ]]; then<br /> <i># Threshold is a percentage</i><br /> thresh=$(( tot_mem * ${2%\%} / 100 ))<br /> else<br /> <i># Threshold is neither a number nor a percentage</i><br /> echo "$PROGNAME: Threshold must be integer or percentage"<br /> print_usage<br /> exit $STATE_UNKNOWN<br /> fi<br /> [[ "$1" = *-w* ]] && thresh_warn=$thresh || thresh_crit=$thresh<br /> shift 2<br /> ;;<br /> -?)<br /> print_usage<br /> exit $STATE_OK<br /> ;;<br /> *)<br /> echo "$PROGNAME: Invalid option '$1'"<br /> print_usage<br /> exit $STATE_UNKNOWN<br /> ;;<br /> esac<br />done<br /><br />if [[ -z "$thresh_warn" || -z "$thresh_crit" ]]; then<br /> <i># One or both thresholds were not specified</i><br /> echo "$PROGNAME: Threshold not set"<br /> print_usage<br /> exit $STATE_UNKNOWN<br />elif [[ "$thresh_crit" -gt "$thresh_warn" ]]; then<br /> <i># The warning threshold must be greater than the critical threshold</i><br /> echo "$PROGNAME: Warning free space should be more than critical free space"<br /> print_usage<br /> exit $STATE_UNKNOWN<br />fi<br /><br />if [[ "$verbosity" -ge 2 ]]; then<br /> <i># Print debugging information</i><br /> /bin/cat <<__EOT<br />Debugging information:<br />Warning threshold: $thresh_warn MB<br />Critical threshold: $thresh_crit MB<br />Verbosity level: $verbosity<br />Total memory: $tot_mem MB<br />Free memory: $free_mem MB ($free_mem_perc%)<br />__EOT<br />fi<br /><br />if [[ "$free_mem" -lt "$thresh_crit" ]]; then<br /> <i># Free memory is less than the critical threshold</i><br /> echo "MEMORY CRITICAL - $free_mem_perc% free ($free_mem MB out of $tot_mem MB)"<br /> exit $STATE_CRITICAL<br />elif [[ "$free_mem" -lt "$thresh_warn" ]]; then<br /> <i># Free memory is less than the warning threshold</i><br /> echo "MEMORY WARNING - $free_mem_perc% free ($free_mem MB out of $tot_mem MB)"<br /> exit $STATE_WARNING<br />else<br /> <i># There's enough free memory!</i><br /> echo "MEMORY OK - $free_mem_perc% free ($free_mem MB out of $tot_mem MB)"<br /> exit $STATE_OK<br />fi<br /></limit></limit></pre> </div><pre><br /></pre> <div style='clear: both;'></div> </div> <div class='post-footer'> <div class='post-footer-line post-footer-line-1'> <span class='post-author vcard'> Posted by <span class='fn' itemprop='author' itemscope='itemscope' itemtype='http://schema.org/Person'> <meta content='https://www.blogger.com/profile/08055786710159541445' itemprop='url'/> <a class='g-profile' href='https://www.blogger.com/profile/08055786710159541445' rel='author' title='author profile'> <span itemprop='name'>virendersharma</span> </a> </span> </span> <span class='post-timestamp'> at <meta content='http://virendersharma.blogspot.com/2009/04/network-monitoring-with-nagios-and.html' itemprop='url'/> <a class='timestamp-link' href='https://virendersharma.blogspot.com/2009/04/network-monitoring-with-nagios-and.html' rel='bookmark' title='permanent link'><abbr class='published' itemprop='datePublished' title='2009-04-16T06:00:00-07:00'>6:00 AM</abbr></a> </span> <span class='post-comment-link'> <a class='comment-link' href='https://virendersharma.blogspot.com/2009/04/network-monitoring-with-nagios-and.html#comment-form' onclick=''> No comments: </a> </span> <span class='post-icons'> <span class='item-control blog-admin pid-463720878'> <a href='https://www.blogger.com/post-edit.g?blogID=7460292314936920729&postID=4489830738780296028&from=pencil' title='Edit Post'> <img alt='' class='icon-action' height='18' src='https://resources.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/> </a> </span> </span> <div class='post-share-buttons goog-inline-block'> </div> </div> <div class='post-footer-line post-footer-line-2'> <span class='post-labels'> </span> </div> <div class='post-footer-line post-footer-line-3'> <span class='post-location'> </span> </div> </div> </div> </div> </div></div> </div> <div class='blog-pager' id='blog-pager'> <span id='blog-pager-older-link'> <a class='blog-pager-older-link' href='https://virendersharma.blogspot.com/search?updated-max=2009-04-16T06:00:00-07:00&max-results=7' id='Blog1_blog-pager-older-link' title='Older Posts'>Older Posts</a> </span> <a class='home-link' href='https://virendersharma.blogspot.com/'>Home</a> </div> <div class='clear'></div> <div class='blog-feeds'> <div class='feed-links'> Subscribe to: <a class='feed-link' href='https://virendersharma.blogspot.com/feeds/posts/default' target='_blank' type='application/atom+xml'>Posts (Atom)</a> </div> </div> </div></div> </div> <div id='sidebar-wrapper'> <div class='sidebar section' id='sidebar'><div class='widget Followers' data-version='1' id='Followers1'> <h2 class='title'>Followers</h2> <div class='widget-content'> <div id='Followers1-wrapper'> <div style='margin-right:2px;'> <div><script type="text/javascript" src="https://apis.google.com/js/platform.js"></script> <div id="followers-iframe-container"></div> <script type="text/javascript"> window.followersIframe = null; function followersIframeOpen(url) { gapi.load("gapi.iframes", function() { if (gapi.iframes && gapi.iframes.getContext) { window.followersIframe = gapi.iframes.getContext().openChild({ url: url, where: document.getElementById("followers-iframe-container"), messageHandlersFilter: gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER, messageHandlers: { '_ready': function(obj) { window.followersIframe.getIframeEl().height = obj.height; }, 'reset': function() { window.followersIframe.close(); followersIframeOpen("https://www.blogger.com/followers/frame/7460292314936920729?colors\x3dCgt0cmFuc3BhcmVudBILdHJhbnNwYXJlbnQaByMwMDAwMDAiByM5OTk5OTkqByNmZmZmZmYyByMwMDAwMDA6ByMwMDAwMDBCByM5OTk5OTlKByMwMDAwMDBSByM5OTk5OTlaC3RyYW5zcGFyZW50\x26pageSize\x3d21\x26hl\x3den\x26origin\x3dhttps://virendersharma.blogspot.com"); }, 'open': function(url) { window.followersIframe.close(); followersIframeOpen(url); } } }); } }); } followersIframeOpen("https://www.blogger.com/followers/frame/7460292314936920729?colors\x3dCgt0cmFuc3BhcmVudBILdHJhbnNwYXJlbnQaByMwMDAwMDAiByM5OTk5OTkqByNmZmZmZmYyByMwMDAwMDA6ByMwMDAwMDBCByM5OTk5OTlKByMwMDAwMDBSByM5OTk5OTlaC3RyYW5zcGFyZW50\x26pageSize\x3d21\x26hl\x3den\x26origin\x3dhttps://virendersharma.blogspot.com"); </script></div> </div> </div> <div class='clear'></div> </div> </div><div class='widget BlogArchive' data-version='1' id='BlogArchive1'> <h2>Blog Archive</h2> <div class='widget-content'> <div id='ArchiveList'> <div id='BlogArchive1_ArchiveList'> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='https://virendersharma.blogspot.com/2011/'> 2011 </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='hierarchy'> <li class='archivedate expanded'> <a class='toggle' href='javascript:void(0)'> <span class='zippy toggle-open'> ▼  </span> </a> <a class='post-count-link' href='https://virendersharma.blogspot.com/2011/09/'> September </a> <span class='post-count' dir='ltr'>(2)</span> <ul class='posts'> <li><a href='https://virendersharma.blogspot.com/2011/09/perl-one-liner.html'>Perl One-liner</a></li> <li><a href='https://virendersharma.blogspot.com/2011/09/configuring-odbc-with-php-oracle.html'>configuring odbc with php & oracle.</a></li> </ul> </li> </ul> </li> </ul> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://virendersharma.blogspot.com/2009/'> 2009 </a> <span class='post-count' dir='ltr'>(4)</span> <ul class='hierarchy'> <li class='archivedate collapsed'> <a class='toggle' href='javascript:void(0)'> <span class='zippy'> ►  </span> </a> <a class='post-count-link' href='https://virendersharma.blogspot.com/2009/04/'> April </a> <span class='post-count' dir='ltr'>(4)</span> </li> </ul> </li> </ul> </div> </div> <div class='clear'></div> </div> </div><div class='widget Profile' data-version='1' id='Profile1'> <h2>About Me</h2> <div class='widget-content'> <dl class='profile-datablock'> <dt class='profile-data'> <a class='profile-name-link g-profile' href='https://www.blogger.com/profile/08055786710159541445' rel='author' style='background-image: url(//www.blogger.com/img/logo-16.png);'> virendersharma </a> </dt> </dl> <a class='profile-link' href='https://www.blogger.com/profile/08055786710159541445' rel='author'>View my complete profile</a> <div class='clear'></div> </div> </div></div> </div> <!-- spacer for skins that want sidebar and main to be the same height--> <div class='clear'> </div> </div> <!-- end content-wrapper --> </div></div> <!-- end outer-wrapper --> <script type="text/javascript" src="https://www.blogger.com/static/v1/widgets/3935100173-widgets.js"></script> <script type='text/javascript'> window['__wavt'] = 'AEUoTZp6ZFdfwJatSdzBiDNSDKJF:1782831899465';_WidgetManager._Init('//www.blogger.com/rearrange?blogID\x3d7460292314936920729','//virendersharma.blogspot.com/','7460292314936920729'); _WidgetManager._SetDataContext([{'name': 'blog', 'data': {'blogId': '7460292314936920729', 'title': 'virendersharma', 'url': 'https://virendersharma.blogspot.com/', 'canonicalUrl': 'http://virendersharma.blogspot.com/', 'homepageUrl': 'https://virendersharma.blogspot.com/', 'searchUrl': 'https://virendersharma.blogspot.com/search', 'canonicalHomepageUrl': 'http://virendersharma.blogspot.com/', 'blogspotFaviconUrl': 'https://virendersharma.blogspot.com/favicon.ico', 'bloggerUrl': 'https://www.blogger.com', 'hasCustomDomain': false, 'httpsEnabled': true, 'enabledCommentProfileImages': true, 'gPlusViewType': 'FILTERED_POSTMOD', 'adultContent': false, 'analyticsAccountNumber': '', 'encoding': 'UTF-8', 'locale': 'en', 'localeUnderscoreDelimited': 'en', 'languageDirection': 'ltr', 'isPrivate': false, 'isMobile': false, 'isMobileRequest': false, 'mobileClass': '', 'isPrivateBlog': false, 'isDynamicViewsAvailable': true, 'feedLinks': '\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22virendersharma - Atom\x22 href\x3d\x22https://virendersharma.blogspot.com/feeds/posts/default\x22 /\x3e\n\x3clink rel\x3d\x22alternate\x22 type\x3d\x22application/rss+xml\x22 title\x3d\x22virendersharma - RSS\x22 href\x3d\x22https://virendersharma.blogspot.com/feeds/posts/default?alt\x3drss\x22 /\x3e\n\x3clink rel\x3d\x22service.post\x22 type\x3d\x22application/atom+xml\x22 title\x3d\x22virendersharma - Atom\x22 href\x3d\x22https://www.blogger.com/feeds/7460292314936920729/posts/default\x22 /\x3e\n', 'meTag': '\x3clink rel\x3d\x22me\x22 href\x3d\x22https://www.blogger.com/profile/08055786710159541445\x22 /\x3e\n', 'adsenseHostId': 'ca-host-pub-1556223355139109', 'adsenseHasAds': false, 'adsenseAutoAds': false, 'boqCommentIframeForm': true, 'loginRedirectParam': '', 'view': '', 'dynamicViewsCommentsSrc': '//www.blogblog.com/dynamicviews/4224c15c4e7c9321/js/comments.js', 'dynamicViewsScriptSrc': '//www.blogblog.com/dynamicviews/f344cc2f9db0fa03', 'plusOneApiSrc': 'https://apis.google.com/js/platform.js', 'disableGComments': true, 'interstitialAccepted': false, 'sharing': {'platforms': [{'name': 'Get link', 'key': 'link', 'shareMessage': 'Get link', 'target': ''}, {'name': 'Facebook', 'key': 'facebook', 'shareMessage': 'Share to Facebook', 'target': 'facebook'}, {'name': 'BlogThis!', 'key': 'blogThis', 'shareMessage': 'BlogThis!', 'target': 'blog'}, {'name': 'X', 'key': 'twitter', 'shareMessage': 'Share to X', 'target': 'twitter'}, {'name': 'Pinterest', 'key': 'pinterest', 'shareMessage': 'Share to Pinterest', 'target': 'pinterest'}, {'name': 'Email', 'key': 'email', 'shareMessage': 'Email', 'target': 'email'}], 'disableGooglePlus': true, 'googlePlusShareButtonWidth': 0, 'googlePlusBootstrap': '\x3cscript type\x3d\x22text/javascript\x22\x3ewindow.___gcfg \x3d {\x27lang\x27: \x27en\x27};\x3c/script\x3e'}, 'hasCustomJumpLinkMessage': false, 'jumpLinkMessage': 'Read more', 'pageType': 'index', 'pageName': '', 'pageTitle': 'virendersharma'}}, {'name': 'features', 'data': {}}, {'name': 'messages', 'data': {'edit': 'Edit', 'linkCopiedToClipboard': 'Link copied to clipboard!', 'ok': 'Ok', 'postLink': 'Post Link'}}, {'name': 'template', 'data': {'isResponsive': false, 'isAlternateRendering': false, 'isCustom': false}}, {'name': 'view', 'data': {'classic': {'name': 'classic', 'url': '?view\x3dclassic'}, 'flipcard': {'name': 'flipcard', 'url': '?view\x3dflipcard'}, 'magazine': {'name': 'magazine', 'url': '?view\x3dmagazine'}, 'mosaic': {'name': 'mosaic', 'url': '?view\x3dmosaic'}, 'sidebar': {'name': 'sidebar', 'url': '?view\x3dsidebar'}, 'snapshot': {'name': 'snapshot', 'url': '?view\x3dsnapshot'}, 'timeslide': {'name': 'timeslide', 'url': '?view\x3dtimeslide'}, 'isMobile': false, 'title': 'virendersharma', 'description': '', 'url': 'https://virendersharma.blogspot.com/', 'type': 'feed', 'isSingleItem': false, 'isMultipleItems': true, 'isError': false, 'isPage': false, 'isPost': false, 'isHomepage': true, 'isArchive': false, 'isLabelSearch': false}}]); _WidgetManager._RegisterWidget('_NavbarView', new _WidgetInfo('Navbar1', 'navbar', document.getElementById('Navbar1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_HeaderView', new _WidgetInfo('Header1', 'header', document.getElementById('Header1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogView', new _WidgetInfo('Blog1', 'main', document.getElementById('Blog1'), {'cmtInteractionsEnabled': false, 'lightboxEnabled': true, 'lightboxModuleUrl': 'https://www.blogger.com/static/v1/jsbin/113638092-lbx.js', 'lightboxCssUrl': 'https://www.blogger.com/static/v1/v-css/828616780-lightbox_bundle.css'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_FollowersView', new _WidgetInfo('Followers1', 'sidebar', document.getElementById('Followers1'), {}, 'displayModeFull')); _WidgetManager._RegisterWidget('_BlogArchiveView', new _WidgetInfo('BlogArchive1', 'sidebar', document.getElementById('BlogArchive1'), {'languageDirection': 'ltr', 'loadingMessage': 'Loading\x26hellip;'}, 'displayModeFull')); _WidgetManager._RegisterWidget('_ProfileView', new _WidgetInfo('Profile1', 'sidebar', document.getElementById('Profile1'), {}, 'displayModeFull')); </script> </body> </html>