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