monit-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[monit-dev] Monit control via unix socket


From: Andea Bonomi
Subject: [monit-dev] Monit control via unix socket
Date: Fri, 15 Jul 2011 16:43:30 +0200
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20110624 Thunderbird/5.0

Hello,
I have developed a patch for interacting with monit not only through tcp/ip but also via socket. We use monit to start/stop all the services in our linux-based network products. Sometimes, reconfiguring the system
the network is not available, so some services are not started/restarted.
(Yes, also the loopback interface sometimes is not available...)
With this patch is it possible to specify a unix socket to be used for the comunication between the monitor clients and the server.
The unix socket is (obviously) only local and can be used only my the root.
An example of configuration for (monitrc) is the following:

set httpd port 2812 and
      use address localhost
      unixsocket "/var/run/monit.sock"

Here we enable the httpd server on port 2812 on localhost and also on the socke named "/var/run/monit.sock".

I hope this feature could be useful to someone.
Thank you for the good job on monit!
Cheers,
Andrea

--
--
:: e n d i a n
:: security with passion

:: Andrea Bonomi
:: Senior Software Engineer



Index: src/http/engine.c
===================================================================
--- src/http/engine.c    (revision 396)
+++ src/http/engine.c    (working copy)
@@ -129,6 +129,8 @@
   unsigned long mask;
 };

+static int myUnixServerSocket= 0;
+static volatile int stoppedUnix= FALSE;

/* -------------------------------------------------------------- Prototypes */

@@ -656,7 +658,7 @@
     goto error;
   }

-  if(! authenticate(in.sin_addr)) {
+  if((in.sin_family != AF_UNIX) && (! authenticate(in.sin_addr))) {
     goto error;
   }

@@ -688,3 +690,61 @@

 }

+
+
+/* ------------------------------------------------------------- Unix Socket */
+
+
+/**
+ * Start the HTTPD server on unix socket
+ * @param backlog The maximum length of the incomming connection queue
+ * @param bindAddr the socket path the server will bind to
+ */
+void start_httpd_unix(int backlog, char *socketPath) {
+
+  Socket_T S= NULL;
+
+  stoppedUnix= Run.stopped;
+
+ if((myUnixServerSocket= create_server_socket(0, backlog, socketPath)) < 0) {
+
+    LogError("http server: Could not create a server socket at %s -- %s\n",
+    socketPath, STRERROR);
+
+    LogError("monit HTTP server not available\n");
+
+    if(Run.init) {
+
+      sleep(1);
+      kill_daemon(SIGTERM);
+
+    }
+
+  } else {
+
+    while(! stoppedUnix) {
+
+      if(!(S= socket_producer(myUnixServerSocket, 0, NULL))) {
+           continue;
+      }
+
+      http_processor(S);
+
+    }
+
+    close_socket(myUnixServerSocket);
+
+  }
+
+}
+
+
+/**
+ * Stop the HTTPD server on unix socket
+ */
+void stop_httpd_unix() {
+
+  stoppedUnix = TRUE;
+
+}
+
Index: src/http/engine.h
===================================================================
--- src/http/engine.h    (revision 396)
+++ src/http/engine.h    (working copy)
@@ -53,5 +53,7 @@
 int has_hosts_allow();
 void destroy_hosts_allow();

+void start_httpd_unix(int backlog, char *socketPath);
+void stop_httpd_unix();

 #endif
Index: src/http.c
===================================================================
--- src/http.c    (revision 396)
+++ src/http.c    (working copy)
@@ -62,9 +62,11 @@

 /* Private prototypes */
 static void *thread_wrapper(void *arg);
+static void *thread_wrapper_unix(void *arg);

 /* The HTTP Thread */
 static pthread_t thread;
+static pthread_t threadUnix;

 static volatile int running = FALSE;

@@ -130,6 +132,17 @@
       LogInfo("%s HTTP server stopped\n", prog);
       running = FALSE;
     }
+
+    if (Run.bind_path) {
+      LogInfo("Shutting down %s server on %s\n", prog, Run.bind_path);
+      stop_httpd_unix();
+      if( (status= pthread_join(threadUnix, NULL)) != 0) {
+ LogError("%s: Failed to stop the server on %s. Thread error -- %s.\n",
+            prog, Run.bind_path, strerror(status));
+      } else {
+        LogInfo("%s server on %s stopped\n", prog, Run.bind_path);
+      }
+    }
     break;

   case START_HTTP:
@@ -142,6 +155,15 @@
       LogInfo("%s HTTP server started\n", prog);
       running = TRUE;
     }
+    if (Run.bind_path) {
+      LogInfo("Starting %s server at %s\n", prog, Run.bind_path);
+ if( (status= pthread_create(&threadUnix, NULL, thread_wrapper_unix, NULL)) != 0) { + LogError("%s: Failed to create the server on %s. Thread error -- %s.\n",
+          prog, Run.bind_path, strerror(status));
+      } else {
+        LogInfo("%s server on %s started\n", prog, Run.bind_path);
+      }
+    }
     break;

   default:
@@ -171,4 +193,17 @@

 }

+static void *thread_wrapper_unix(void *arg) {
+
+  sigset_t ns;
+
+  /* Block collective signals in the http thread. The http server is
+   * taken down gracefully by signaling the main monit thread */
+  set_signal_block(&ns, NULL);
+  start_httpd_unix(1024, Run.bind_path);
+
+  return NULL;
+
+}
+

Index: src/control.c
===================================================================
--- src/control.c    (revision 396)
+++ src/control.c    (working copy)
@@ -105,7 +105,7 @@
     return FALSE;
   }

- s = socket_new(Run.bind_addr ? Run.bind_addr : "localhost", Run.httpdport, SOCKET_TCP, Run.httpdssl, NET_TIMEOUT); + s = socket_new(Run.bind_path?Run.bind_path:Run.bind_addr ? Run.bind_addr : "localhost", Run.httpdport, SOCKET_TCP, Run.httpdssl, NET_TIMEOUT);
   if (!s) {
LogError("%s: Cannot connect to the monit daemon. Did you start it with http support?\n", prog);
     return FALSE;
Index: src/status.c
===================================================================
--- src/status.c    (revision 396)
+++ src/status.c    (working copy)
@@ -90,7 +90,7 @@
     return status;
   }

- if(!(sock= socket_new(Run.bind_addr?Run.bind_addr:"localhost", Run.httpdport, + if(!(sock= socket_new(Run.bind_path?Run.bind_path:Run.bind_addr?Run.bind_addr:"localhost", Run.httpdport,
                         SOCKET_TCP, Run.httpdssl, NET_TIMEOUT))) {
     LogError("%s: error connecting to the monit daemon\n", prog);
     return status;
Index: src/p.y
===================================================================
--- src/p.y    (revision 396)
+++ src/p.y    (working copy)
@@ -693,6 +693,7 @@
                 ;

 bindaddress     : ADDRESS STRING { Run.bind_addr = $2; }
+                | UNIXSOCKET PATH { Run.bind_path = $2; }
                 ;

 pemfile         : PEMFILE PATH {
Index: src/net.c
===================================================================
--- src/net.c    (revision 396)
+++ src/net.c    (working copy)
@@ -370,7 +370,44 @@
   int status;
   int flag = 1;
   struct sockaddr_in myaddr;
+
+ if((bindAddr) && (strlen(bindAddr) > 0) && (bindAddr[0] == '/')) { /* UNIX socket */
+    struct sockaddr_un serveraddr;

+    LogInfo("Starting %s HTTP server on socket %s\n", prog, bindAddr);
+
+    if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+      LogError("%s: Cannot create unix socket -- %s\n", prog, STRERROR);
+      return -1;
+    }
+
+    memset(&serveraddr, 0, sizeof(serveraddr));
+    serveraddr.sun_family = AF_UNIX;
+    strcpy(serveraddr.sun_path, bindAddr);
+
+    if(! set_noblock(s))
+      goto error;
+
+    if(fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
+ LogError("%s: Cannot set close on exec option -- %s\n", prog, STRERROR);
+      goto error;
+    }
+
+    unlink(bindAddr); /* Remove any old socket */
+ if(bind(s, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in)) < 0) {
+      LogError("%s: Cannot bind -- %s\n", prog, STRERROR);
+      goto error;
+    }
+    chmod(bindAddr, 0600);
+
+    if(listen(s, backlog) < 0) {
+      LogError("%s: Cannot listen -- %s\n", prog, STRERROR);
+      goto error;
+    }
+
+    return s;
+  }
+
   if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
     LogError("%s: Cannot create socket -- %s\n", prog, STRERROR);
     return -1;
Index: src/socket.c
===================================================================
--- src/socket.c    (revision 396)
+++ src/socket.c    (working copy)
@@ -169,6 +169,32 @@
   }
   ASSERT(timeout>0);

+  if ((host) && (strlen(host) >0) && (host[0] == '/')) {
+    if((s= create_unix_socket(host, timeout)) != -1) {
+
+      Socket_T S= NULL;
+
+      NEW(S);
+      S->socket= s;
+      S->length= 0;
+      S->offset= 0;
+      S->port= port;
+      S->type= proto;
+      S->timeout= timeout;
+      S->host= xstrdup(host);
+      S->connection_type= TYPE_LOCAL;
+
+      if(ssl.use_ssl && !socket_switch2ssl(S, ssl)) {
+        socket_free(&S);
+        return NULL;
+      }
+
+      return S;
+    }
+
+    return NULL;
+  }
+
   if((s= create_socket(host, port, proto, timeout)) != -1) {

     Socket_T S= NULL;
Index: src/monit.h
===================================================================
--- src/monit.h    (revision 396)
+++ src/monit.h    (working copy)
@@ -828,6 +828,7 @@
int facility; /** The facility to use when running openlog() */ int doprocess; /**< TRUE if process status engine is used */ char *bind_addr; /**< The address monit http will bind to */ + char *bind_path; /**< The unix socket path monit http will bind to */ volatile int doreload; /**< TRUE if a monit daemon should reinitialize */ volatile int dowakeup; /**< TRUE if a monit daemon was wake up by signal */ int doaction; /**< TRUE if some service(s) has action pending */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]