00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <errno.h>
00025 #include <signal.h>
00026
00027 #ifdef HAVE_GETOPT_H
00028 #include <getopt.h>
00029 #endif
00030
00031 #ifdef HAVE_STRING_H
00032 #include <string.h>
00033 #endif
00034
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038
00039 #ifdef HAVE_SYS_TYPES_H
00040 #include <sys/types.h>
00041 #endif
00042
00043 #ifdef HAVE_SYS_STAT_H
00044 #include <sys/stat.h>
00045 #endif
00046
00047
00048 #include "monitor.h"
00049 #include "net.h"
00050 #include "ssl.h"
00051 #include "monit_process.h"
00052
00070
00071 static void do_init();
00072 static RETSIGTYPE do_reload(int);
00073 static void do_reinit();
00074 static void do_action(char **);
00075 static RETSIGTYPE do_destroy(int);
00076 static void do_default();
00077 static RETSIGTYPE do_wakeup(int);
00078 static int do_wakeupcall();
00079 static void handle_options(int, char **);
00080 static void help();
00081 static void version();
00082 static void stop_http();
00083 static void start_http();
00084
00085
00089 int main(int argc, char **argv) {
00090
00091 prog= stripfilename(argv[0]);
00092 init_env();
00093 handle_options(argc, argv);
00094
00095 do_init();
00096 do_action(argv);
00097 do_destroy(SIGSTOP);
00098
00099 exit(0);
00100
00101 }
00102
00103
00104
00105
00106
00112 static void do_init() {
00113
00114 int status;
00115
00116
00117
00118
00119
00120
00121 signal(SIGTERM, do_destroy);
00122
00123
00124
00125
00126
00127
00128 signal(SIGUSR1, do_wakeup);
00129
00130
00131
00132
00133
00134
00135 signal(SIGHUP, do_reload);
00136
00137
00138
00139
00140 signal(SIGPIPE, SIG_IGN);
00141
00142
00143
00144
00145
00146
00147 status= pthread_mutex_init(&Run.mutex, NULL);
00148 if(status != 0) {
00149
00150 log("%s: Cannot initialize mutex -- %s\n", prog, strerror(status));
00151 exit(1);
00152
00153 }
00154
00155
00156
00157
00158 if(! Run.controlfile) {
00159
00160 Run.controlfile= find_rcfile();
00161
00162 }
00163
00164
00165
00166
00167 Run.doprocess= init_process_info();
00168
00169
00170
00171
00172
00173 if(! parse(Run.controlfile)) {
00174
00175 exit(1);
00176
00177 }
00178
00179
00180
00181
00182
00183
00184
00185 if(Run.testing) {
00186
00187 error("Control file syntax OK\n");
00188 exit(0);
00189
00190 }
00191
00192
00193
00194
00195 if(! log_init()) {
00196
00197 exit(1);
00198
00199 }
00200
00201
00202
00203
00204 if(! processlist) {
00205
00206 log("%s: No programs have been specified\n", prog);
00207 exit(0);
00208
00209 }
00210
00211
00212
00213
00214 init_files();
00215
00216
00217
00218
00219 if(Run.debug && Run.have_tty) {
00220
00221 printrunlist();
00222 printprocesslist();
00223
00224 }
00225
00226 }
00227
00228
00233 static void do_reinit() {
00234
00235 char *bind_addr;
00236 int port= Run.httpdport;
00237
00238 Run.doreload= FALSE;
00239
00240 bind_addr= Run.bind_addr?xstrdup(Run.bind_addr):NULL;
00241
00242 log("Awakened by the SIGHUP signal\n");
00243 log("Reinitializing %s - Control file '%s'\n",
00244 prog, Run.controlfile);
00245
00246
00247 gc();
00248
00249 finalize_files();
00250
00251 if(! parse(Run.controlfile)) {
00252
00253 log("%s daemon died\n", prog);
00254 exit(1);
00255
00256 }
00257
00258
00259 log_close();
00260
00261
00262 if(! log_init()) {
00263
00264 exit(1);
00265
00266 }
00267
00268
00269 if(! processlist) {
00270
00271 log("%s: No programs have been specified\n", prog);
00272 exit(0);
00273
00274 }
00275
00276
00277 init_files();
00278
00279 if(! create_pidfile(Run.pidfile)) {
00280
00281 log("%s daemon died\n", prog);
00282 exit(1);
00283
00284 }
00285
00286 if(! can_http()) {
00287
00288 stop_http();
00289
00290 } else if(!is(bind_addr, Run.bind_addr) || port != Run.httpdport) {
00291
00292 stop_http();
00293 start_http();
00294
00295 } else if(! check_httpd()) {
00296
00297 start_http();
00298
00299 }
00300
00301 free(bind_addr);
00302
00303 }
00304
00305
00309 static void do_action(char **args) {
00310
00311 char *action= args[optind];
00312 char *P= args[++optind];
00313
00314 if(! action) {
00315
00316 do_default();
00317
00318 } else if(is(action, "start")) {
00319
00320 if(P) {
00321 if(exist_daemon()) {
00322 d_check_process(P, "start");
00323 } else {
00324 check_process(P, "start");
00325 }
00326 } else {
00327
00328 if(Run.mygroup)
00329 control_group(Run.mygroup, "start");
00330 else
00331 control("start");
00332 }
00333
00334 } else if(is(action, "stop")) {
00335
00336 if(P) {
00337 if(exist_daemon()) {
00338 d_check_process(P, "stop");
00339 } else {
00340 check_process(P, "stop");
00341 }
00342 } else {
00343
00344 if(Run.mygroup)
00345 control_group(Run.mygroup, "stop");
00346 else
00347 control("stop");
00348 }
00349
00350 } else if(is(action, "reload")) {
00351
00352 error("Reinitializing monit daemon\n", prog);
00353 kill_daemon(SIGHUP);
00354
00355 } else if(is(action, "restart")) {
00356
00357 if(P) {
00358
00359 if(! exist_process(P)) {
00360
00361 error("%s: Cannot restart program '%s' -- not found in %s\n",
00362 prog, P, Run.controlfile);
00363
00364 return;
00365
00366 }
00367
00368 if(exist_daemon()) {
00369 d_check_process(P, "restart");
00370 } else {
00371 check_process(P, "restart");
00372 }
00373
00374 } else {
00375
00376 if(Run.mygroup)
00377 control_group(Run.mygroup, "restart");
00378 else
00379 control("restart");
00380 }
00381
00382 } else if(is(action, "status")) {
00383
00384 if(Run.mygroup) {
00385 status_group(Run.mygroup);
00386 } else {
00387 status();
00388 }
00389
00390 } else if(is(action, "quit")) {
00391
00392 error("Stopping monit daemon\n", prog);
00393 kill_daemon(SIGTERM);
00394
00395 } else if(is(action, "validate")) {
00396
00397 validate();
00398
00399 } else {
00400
00401 error("%s: invalid argument -- %s (-h will show valid arguments)\n",
00402 prog, action);
00403 exit(1);
00404
00405 }
00406
00407 reset_depend();
00408
00409 }
00410
00411
00415 static RETSIGTYPE do_wakeup(int sig) {
00416
00417 signal(SIGUSR1, SIG_IGN);
00418 log("Awakened by User defined signal 1\n");
00419 signal(SIGUSR1, do_wakeup);
00420
00421 }
00422
00423
00427 static RETSIGTYPE do_reload(int sig) {
00428
00429 signal(SIGHUP, SIG_IGN);
00430 Run.doreload= TRUE;
00431 signal(SIGHUP, do_reload);
00432
00433 }
00434
00435
00440 static int do_wakeupcall() {
00441
00442 pid_t pid;
00443
00444 if((pid= exist_daemon()) > 0) {
00445
00446 kill(pid, SIGUSR1);
00447 error("%s daemon at %d awakened\n", prog, pid);
00448
00449 return TRUE;
00450
00451 }
00452
00453 return FALSE;
00454
00455 }
00456
00457
00461 static RETSIGTYPE do_destroy(int sig) {
00462
00463 switch(sig) {
00464
00465 case SIGTERM:
00466
00467 stop_http();
00468
00469 if(Run.isdaemon) {
00470
00471 log("%s daemon with pid [%d] killed\n", prog, (int)getpid());
00472
00473 }
00474
00475 finalize_files();
00476
00477
00478 default:
00479
00480 gc();
00481 log_close();
00482 exit(0);
00483
00484 }
00485
00486 }
00487
00488
00494 static void do_default() {
00495
00496 if(Run.isdaemon) {
00497
00498 if(do_wakeupcall()) {
00499
00500 exit(0);
00501
00502 }
00503
00504 log("Starting %s daemon\n", prog);
00505
00506 if(can_http()) {
00507
00508 log("Starting httpd at [%s:%d]\n",
00509 Run.bind_addr?Run.bind_addr:"*", Run.httpdport);
00510
00511 }
00512
00513 if(Run.init != TRUE)
00514 daemonize();
00515
00516 if(! create_pidfile(Run.pidfile)) {
00517
00518 log("%s daemon died\n", prog);
00519 exit(1);
00520
00521 }
00522
00523 if(can_http()) {
00524
00525 start_http();
00526
00527 }
00528
00529 for(;;) {
00530
00531 if(Run.validate != TRUE) {
00532 validate();
00533 } else {
00534 Run.validate= FALSE;
00535 }
00536
00537 sleep(Run.polltime);
00538
00539 if(Run.doreload)
00540 do_reinit();
00541
00542 }
00543
00544 }
00545 else {
00546
00547 validate();
00548
00549 }
00550
00551 }
00552
00553
00558 static void handle_options(int argc, char **argv) {
00559
00560 int opt;
00561
00562 opterr= 0;
00563
00564 Run.mygroup=0;
00565
00566 while((opt= getopt(argc,argv,"c:d:g:l:p:iItvVh")) != -1) {
00567
00568 switch(opt) {
00569
00570 case 'c':
00571 Run.controlfile= xstrdup(optarg);
00572 break;
00573
00574 case 'd':
00575 Run.isdaemon= TRUE;
00576 sscanf(optarg, "%d", &Run.polltime);
00577 if(Run.polltime<1) {
00578 error("%s: option -%c requires a natural number\n", prog, opt);
00579 exit(1);
00580 }
00581 break;
00582
00583 case 'g':
00584 Run.mygroup= xstrdup(optarg);
00585 break;
00586
00587 case 'l':
00588 Run.logfile= xstrdup(optarg);
00589 if(is(Run.logfile, "syslog"))
00590 Run.use_syslog= TRUE;
00591 Run.dolog= TRUE;
00592 break;
00593
00594 case 'p':
00595 Run.pidfile= xstrdup(optarg);
00596 break;
00597
00598 case 'i':
00599 Run.validate= TRUE;
00600 break;
00601
00602 case 'I':
00603 Run.init= TRUE;
00604 break;
00605
00606 case 't':
00607 Run.testing= TRUE;
00608 break;
00609
00610 case 'v':
00611 Run.debug= TRUE;
00612 break;
00613
00614 case 'V':
00615 version();
00616 exit(0);
00617 break;
00618
00619 case 'h':
00620 help();
00621 exit(0);
00622 break;
00623
00624 case '?':
00625 switch(optopt) {
00626
00627 case 'c':
00628 case 'd':
00629 case 'g':
00630 case 'l':
00631 case 'p':
00632 error("%s: option -- %c requires an argument\n", prog, optopt);
00633 break;
00634 default:
00635 error("%s: invalid option -- %c (-h will show valid options)\n",
00636 prog, optopt);
00637
00638 }
00639
00640 exit(1);
00641
00642 }
00643
00644 }
00645
00646 }
00647
00648
00652 static void help() {
00653
00654 printf("Usage: %s [options] {arguments}\n", prog);
00655 printf("Options are as follows:\n");
00656 printf(" -c file Use this control file\n");
00657 printf(" -d n Run as a daemon once per n seconds\n");
00658 printf(" -g name Set group name for start, stop, restart and status\n");
00659 printf(" -l logfile Print log information to this file\n");
00660 printf(" -p pidfile Use this lock file in daemon mode\n");
00661 printf(" -i Validate mode, startup in validate mode\n");
00662 printf(" -I Init mode, run from init\n");
00663 printf(" -t Run syntax check for the control file\n");
00664 printf(" -v Verbose mode, work noisy (diagnostic output)\n");
00665 printf(" -V Print version number and patchlevel\n");
00666 printf(" -h Print this text\n");
00667 printf("Optional action arguments for non-daemon mode are as follows:\n");
00668 printf(" start - Start all programs listed in the control file\n");
00669 printf(" start name - Only start the named program in the control file\n");
00670 printf(" stop - Stop all programs listed in the control file\n");
00671 printf(" stop name - Only stop the named program in the control file\n");
00672 printf(" reload - Reinitialize monit\n");
00673 printf(" restart - Stop and start all programs\n");
00674 printf(" restart name - Only restart the named program in the control file\n");
00675 printf(" status - Print status information for each program\n");
00676 printf(" quit - Kill monit daemon process\n");
00677 printf(" validate - Check all programs and start if not running.\n");
00678
00679 }
00680
00681
00685 static void version() {
00686
00687 printf("This is monit version %s\n", VERSION);
00688 printf("Copyright (C) 2000-2003 by Contributors to the monit codebase\n");
00689
00690 }
00691
00692
00696 static void stop_http() {
00697
00698 monit_http(STOP_HTTP);
00699
00700 }
00701
00702
00706 static void start_http() {
00707
00708 monit_http(START_HTTP);
00709
00710 }
00711
00712