Table of Contents

Pid file

top

Keywords: pid file
Q: If a program crashes without removing its pid file, will monit recognize that the program is not running?

A: Yes, Monit will always check that the pid number in a pid file belongs to a running process. If a program crashes and dies in a "normal" manner, then the process ID (pid) will not exist and monit will know that the program is not running and restart it even if a pid file exist. Some servers can crash and leave a zombie process, and appear to run. Monit also test for zombie processes and will raise an alert if a process has become a zombie.

Keywords: pid file
Q: I have a program that does not create its own pid file. Since monit requires all programs to have a pid file, what do I do?

A: Create a wrapper script and have the script create a pid file before it starts the program. Below you can find an example script for starting an imaginary program (a Java program in this case). Assuming that the script is saved in a file called /bin/xyz, you can call this script from monit by using the following in monitrc:

 check process xyz with pidfile /var/run/xyz.pid
       start = "/bin/xyz start"
       stop = "/bin/xyz stop"

The wrapper script:

 #!/bin/bash
 export JAVA_HOME=/usr/local/java/
 CLASSPATH=ajarfile.jar:.

 case $1 in
    start)
       echo $$ > /var/run/xyz.pid;
       exec 2>&1 java -cp ${CLASSPATH} org.something.with.main 1>/tmp/xyz.out 
       ;;
     stop)  
       kill `cat /var/run/xyz.pid` ;;
     *)  
       echo "usage: xyz {start|stop}" ;;
 esac
 exit 0

Keywords: pid file
Q: Tomcat (The Jakarta Servlet Container) does not create a pid file and will put the server in the background.

A: Edit The catalina.sh script and find and remove the '&' character which will put the Tomcat server in the background. Then call tomcats startup.sh and shutdown.sh scripts from a wrapper script like the one mentioned above.

or

If your catalina.sh contains lines with $CATALINA_PID, you can just set CATALINA_PID=/path/file.pid enviroment variable.

Execution Debug

top

Keywords: Executing programs
Q: I'm having trouble getting monit to execute any "start" or "stop" or "exec" program commands. The log file says that they're being executed, and I can't find anything wrong when I run monit in verbose mode.

A: You can debug a script or a program by calling it from bash and redirect output to a file which you can then inspect for errors. For instance to debug exec (the same can be done for start and stop commands):

  if changed timestamp then exec "/bin/bash -c '/path/myscript &>/tmp/myscript.out'"

This will output the result of running /path/myscript to /tmp/myscript.out. The switch -c tell bash to execute the string that follows as a script. The statement, &>file is used to redirect any output from the script (stdout and stderr) to file. Note that there should be no space between & and >.

When debugging, it is recommended to run Monit in verbose mode so you can watch the console and see what Monit is doing. That is, invoke Monit using 'monit -Iv'. Once satisfied that the script works, you may want to remove the extra call to bash. In that case, the above would be

  if changed timestamp then exec "/path/myscript'"

Finally, Monit uses the system call execv to execute a program or a script. This means that you cannot write shell commands directly in the start, stop or exec statements. To do this, you must do as above; start a shell and issue your commands there. For example:

  start program = "/bin/bash -c 'my shell command && my other command'"

Connection

top

Keywords: Connection testing
Q: I have started monit with HTTP support, but when I telnet into the monit http port the connection closes.

A: If you use the host allow statement, monit will promptly close all connections from hosts it does not find in the host allow list. So make sure that you use the official name for your host or its IP address. If you have a firewall running also make sure that it does not block connections on the monit port.

Connection Failed

top

[I'm] hoping that this helps someone somewhere in the future. Skip the text and jump to the solution at the bottom if you are not interested in my adventure. I write this purely because googling for the error message did not show up with a single useful entry.

Since yesterday I received the message "connection failed, INET[www.example.com:80] via TCP is not ready for i|o -- Interrupted system call" every 5 minutes from a monit instance.

Sometimes it skipped the five minutes and came back after ten minutes or more (but always a multiple of five), sometimes it jumped one minute ahead and faulted after six minutes, to continue then again after five.

The server, however, *was* reachable and working (as it tested successfully from another server).

When I investigated further I discovered that the firewall did open all necessary connections, so it wasn't a fault there.

When I tcpdumped the traffic on the monit instance everything worked fine: Monit opens a TCP connection and the whole process of sending SYN, SYN/ACK, ACK, traffic and finally FIN, FIN/ACK etc. went smoothly.

However, every five minutes monit sent a SYNC, received a SYNC/ACK, but instead of acknowledging with an ACK the very next package was a RST.

Duh!

Replaying a configuration from the backup from the day before yesterday didn't help.

Finally I checked /var/log/messages (should have done that at first, but you know how it goes), where I discovered the wonderful "init: Id "mo" respawning too fast: disabled for 5 minutes".

Yes, I start monit from inittab.

Yesterday the switch where this server was connected to died. After reconnecting to another switch everything was fine again, but somehow the init process must have thought that monit was not running, tried to start it only to find out it was already running...

So the solution was very simple:

 SOLUTION:

 a) comment out the "mo:2345:respawn:/usr/bin/monit \-I" from /etc/inittab.
 b) restart the init process ("init q")
 c) stop monit ("monit quit") 
 d) uncomment again the monit entry from inittab.
 e) Restart init again ("init q")
 d) watch your logfile. No more errors

Marcus

Running Monit from Init

top

Keywords: init
Q: How can I run monit from init so it can be respawned in case monit dies unexpectedly?

A: It is recommended that you use Monit version 5 or later when running Monit from init. Use either the 'set init' statement in monits configuration file or use the -I option from the command line. Here's a sample /etc/inittab entry for monit:

 # Run monit in standard runlevels
 mo:2345:respawn:/usr/local/sbin/monit -Ic /etc/monitrc

After you have modified inits configuration file, you can run the following command to re-examine the runlevel and start monit:

 telinit q

If monit is used to monitor services that are also started at boot time (e.g. services started via SYSV init rc scripts or via inittab) then in some situations a special race condition can occur. That is; if a service is slow to start, monit can assume that the service is not running and possibly try to start it and raise an alert, while, in fact the service is already about to start or already in its startup sequence. If you experience this problem, here are a couple of strategies you can use to prevent this type of race condition:

1. Start critical services directly from monit:

This is the recommended solution - let monit takeover the responsibility for starting services. To use this strategy you must turn off the systems automatic start and stop for all services handled by monit.

On RedHat, you can for example use:

  chkconfig --del myservice

on Debian:

  update-rc.d -f myservice remove

a general example:

  mv /etc/rc2.d/S99myservice /etc/rc2.d/s99myservice

If monit is started from a rc script, then to start and stop the service at systems shutdown, you should add the following lines to monit's rc script:

on start:

  /usr/local/bin/monit -c /etc/monitrc start myprocess

on stop:

  /usr/local/bin/monit -c /etc/monitrc stop myprocess

or if monit handles more than one service, simply start/stop all services by using:

on start:

  /usr/local/bin/monit -c /etc/monitrc start all

on stop:

  /usr/local/bin/monit -c /etc/monitrc stop all

If monit instead is started from init then, add a second line to inittab to stop the service:

  mo:2345:respawn:/usr/local/bin/monit -Ic /etc/monitrc
  mon:2345:wait:/usr/local/bin/monit -Ic /etc/monitrc start myprocess
  moff:06:wait:/usr/local/bin/monit -Ic /etc/monitrc stop myprocess

or to stop all services handled by monit:

  mo:2345:respawn:/usr/local/bin/monit -Ic /etc/monitrc
  mon:2345:wait:/usr/local/bin/monit -Ic /etc/monitrc start all
  moff:06:wait:/usr/local/bin/monit -Ic /etc/monitrc stop all

Services handled by monit must have start and stop methods defined so monit can start and stop a service. For instance:

  check process myservice with pidfile /var/run/myservice.pid
        start program = "/etc/init.d/myservice start"
        stop program = "/etc/init.d/myservice stop"

2. Make init wait for a service to start:

This solution will make the init process wait for the service to start before it will continue to start other services. If you are running monit from init, you must enter monit's line at the end of /etc/inittab (A short example):

  si::sysinit:/etc/init.d/rcS
  ...
  l2:2:wait:/etc/init.d/rc 2
  ...
  mo:2345:respawn:/usr/local/bin/monit -Ic /etc/monitrc

The rc script for the monitored service must be so, that it will not return unless the service was started or start of the service timed out. Creative use of sleep(1) may be sufficient.

As in the above example, services handled by monit must have start and stop methods defined.

Running two or more Monit instances on the same machine

top

You can run several Monit instances on the same machine. This is easiest if you run each instance as a different user, because Monit by default read its configuration file as $HOME/.monitrc. In this case, the only change needed is to setup Monit to listen on different ports in each users $HOME/.monitrc file. The statement to modify is

   set httpd port 2812

where the port (in this case 2812) need to be different for each instance.

As the same user

You can also run two or more instances as the same user, but in this case, in addition to changing the port, you must also specify different monitrc files to be used for each instance. Monit uses a lock file to prevent concurrent runs and a state file to save its state between restart. These two files are normally saved as $HOME/.monit.pid and as $HOME/.monit.state. If you run two Monit instances you need to specify different locations for these files. Luckily, this can be done in your monitrc control file. The statements to set are

  set pidfile /var/run/monit-1.pid

and

  set statefile /var/run/monit-1.state

If you use M/Monit you will also need to specify a different location for the Monit id-file. This file contains the unique id of your Monit instance and is reported in to M/Monit. The statement to set in this case is

  set idfile /var/run/monit-1.id

To summarize, each Monit instance need its own monitrc control file and in each file you need to set a different port number, and different locations for the Monit pid-file and state-file. Finally, when you start each Monit instance you must specify the control file explicit on the command line. Assume you plan to start two instances:

  monit -c /path/to/instance-1/monitrc
  monit -c /path/to/instance-2/monitrc

So as you can see, running more instances of Monit on the same machine is no problem, but far easier if it is run by different users as you then only need to change the port number.

Page last modified on March 27, 2014, at 04:23 AM CET

Copyright © 2014 Tildeslash Ltd. All Rights Reserved.