void *start_gearmand(void*data) { int sid; data = data; // warning: unused parameter 'data' pid_t pid = fork(); if(pid == 0) { sid = setsid(); char port[30]; snprintf(port, 30, "--port=%d", GEARMAND_TEST_PORT); /* for newer gearman versions */ if(atof(gearman_version()) >= 0.27) { execlp("gearmand", "gearmand", "--listen=127.0.0.1", "--threads=10", "--job-retries=0", port, "--verbose=DEBUG", "--log-file=/tmp/gearmand.log" , (char *)NULL); } else if(atof(gearman_version()) > 0.14) { execlp("gearmand", "gearmand", "--listen=127.0.0.1", "--threads=10", "--job-retries=0", port, "--verbose=999", "--log-file=/tmp/gearmand.log" , (char *)NULL); } else { /* for gearman 0.14 */ execlp("gearmand", "gearmand", "-t 10", "-j 0", port, (char *)NULL); } perror("gearmand"); exit(1); } else { gearmand_pid = pid; } return NULL; }
/* print version */ void print_version() { printf("send_gearman: version %s running on libgearman %s\n", GM_VERSION, gearman_version()); printf("\n"); exit( STATE_UNKNOWN ); }
/* create a task and send it */ int add_job_to_queue( gearman_client_st *client, char ** server_list, char * queue, char * uniq, char * data, int priority, int retries, int transport_mode, int send_now ) { gearman_task_st *task = NULL; gearman_return_t ret1, ret2; char * crypted_data; int size, free_uniq; struct timeval now; /* check too long queue names */ if(strlen(queue) > 63) { gm_log( GM_LOG_ERROR, "queue name too long: '%s'\n", queue ); return GM_ERROR; } /* cut off to long uniq ids */ free_uniq = 0; if(uniq != NULL && strlen(uniq) > 63) { uniq = strndup(uniq, 63); free_uniq = 1; } signal(SIGPIPE, SIG_IGN); gm_log( GM_LOG_TRACE, "add_job_to_queue(%s, %s, %d, %d, %d, %d)\n", queue, uniq, priority, retries, transport_mode, send_now ); gm_log( GM_LOG_TRACE, "%d --->%s<---\n", strlen(data), data ); crypted_data = malloc(GM_BUFFERSIZE); size = mod_gm_encrypt(&crypted_data, data, transport_mode); gm_log( GM_LOG_TRACE, "%d +++>\n%s\n<+++\n", size, crypted_data ); #ifdef GM_DEBUG /* verify decrypted string is equal to the original */ char * test; test = malloc(GM_BUFFERSIZE); mod_gm_decrypt(&test, crypted_data, transport_mode); gm_log( GM_LOG_TRACE, "%d ===>\n%s\n<===\n", size, test ); if(strcmp(test, data)) { gm_log( GM_LOG_ERROR, "%d --->%s<---\n", strlen(data), data ); gm_log( GM_LOG_ERROR, "%d ===>\n%s\n<===\n", size, test ); fprintf(stderr, "encrypted string does not match\n"); exit(EXIT_FAILURE); } #endif if( priority == GM_JOB_PRIO_LOW ) { task = gearman_client_add_task_low_background( client, NULL, NULL, queue, uniq, ( void * )crypted_data, ( size_t )size, &ret1 ); gearman_task_give_workload(task,crypted_data,size); } else if( priority == GM_JOB_PRIO_NORMAL ) { task = gearman_client_add_task_background( client, NULL, NULL, queue, uniq, ( void * )crypted_data, ( size_t )size, &ret1 ); gearman_task_give_workload(task,crypted_data,size); } else if( priority == GM_JOB_PRIO_HIGH ) { task = gearman_client_add_task_high_background( client, NULL, NULL, queue, uniq, ( void * )crypted_data, ( size_t )size, &ret1 ); gearman_task_give_workload(task,crypted_data,size); } else { gm_log( GM_LOG_ERROR, "add_job_to_queue() wrong priority: %d\n", priority ); } if(send_now != TRUE) return GM_OK; ret2 = gearman_client_run_tasks( client ); gearman_client_task_free_all( client ); if( ret1 != GEARMAN_SUCCESS || ret2 != GEARMAN_SUCCESS || task == NULL || ( gearman_client_error(client) != NULL && atof(gearman_version()) == 0.14 ) ) { /* log the error */ if(retries == 0) { gettimeofday(&now,NULL); /* only log the first error, otherwise we would fill the log very quickly */ if( mod_gm_con_errors == 0 ) { gettimeofday(&mod_gm_error_time,NULL); gm_log( GM_LOG_ERROR, "sending job to gearmand failed: %s\n", gearman_client_error(client) ); } /* or every minute to give an update */ else if( now.tv_sec >= mod_gm_error_time.tv_sec + 60) { gettimeofday(&mod_gm_error_time,NULL); gm_log( GM_LOG_ERROR, "sending job to gearmand failed: %s (%i lost jobs so far)\n", gearman_client_error(client), mod_gm_con_errors ); } mod_gm_con_errors++; } /* recreate client, otherwise gearman sigsegvs */ gearman_client_free( client ); create_client( server_list, client ); /* retry as long as we have retries */ if(retries > 0) { retries--; gm_log( GM_LOG_TRACE, "add_job_to_queue() retrying... %d\n", retries ); return(add_job_to_queue( client, server_list, queue, uniq, data, priority, retries, transport_mode, send_now )); } /* no more retries... */ else { gm_log( GM_LOG_TRACE, "add_job_to_queue() finished with errors: %d %d\n", ret1, ret2 ); return GM_ERROR; } } /* reset error counter */ mod_gm_con_errors = 0; if(free_uniq) free(uniq); gm_log( GM_LOG_TRACE, "add_job_to_queue() finished sucessfully: %d %d\n", ret1, ret2 ); return GM_OK; }
int nebmodule_init( int flags, char *args, nebmodule *handle ) { int i; int broker_option_errors = 0; send_now = FALSE; result_threads_running = 0; /* save our handle */ gearman_module_handle=handle; /* set some module info */ neb_set_module_info( gearman_module_handle, NEBMODULE_MODINFO_TITLE, "Mod-Gearman" ); neb_set_module_info( gearman_module_handle, NEBMODULE_MODINFO_AUTHOR, "Sven Nierlein" ); neb_set_module_info( gearman_module_handle, NEBMODULE_MODINFO_TITLE, "Copyright (c) 2010-2011 Sven Nierlein" ); neb_set_module_info( gearman_module_handle, NEBMODULE_MODINFO_VERSION, GM_VERSION ); neb_set_module_info( gearman_module_handle, NEBMODULE_MODINFO_LICENSE, "GPL v3" ); neb_set_module_info( gearman_module_handle, NEBMODULE_MODINFO_DESC, "distribute host/service checks and eventhandler via gearman" ); mod_gm_opt = malloc(sizeof(mod_gm_opt_t)); set_default_options(mod_gm_opt); /* parse arguments */ gm_log( GM_LOG_DEBUG, "Version %s\n", GM_VERSION ); gm_log( GM_LOG_DEBUG, "args: %s\n", args ); gm_log( GM_LOG_TRACE, "nebmodule_init(%i, %i)\n", flags ); gm_log( GM_LOG_DEBUG, "running on libgearman %s\n", gearman_version() ); if( read_arguments( args ) == GM_ERROR ) return NEB_ERROR; /* check for minimum eventbroker options */ if(!(event_broker_options & BROKER_PROGRAM_STATE)) { gm_log( GM_LOG_ERROR, "mod_gearman needs BROKER_PROGRAM_STATE (%i) event_broker_options enabled to work\n", BROKER_PROGRAM_STATE ); broker_option_errors++; } if(!(event_broker_options & BROKER_TIMED_EVENTS)) { gm_log( GM_LOG_ERROR, "mod_gearman needs BROKER_TIMED_EVENTS (%i) event_broker_options enabled to work\n", BROKER_TIMED_EVENTS ); broker_option_errors++; } if( ( mod_gm_opt->perfdata == GM_ENABLED || mod_gm_opt->hostgroups_num > 0 || mod_gm_opt->hosts == GM_ENABLED ) && !(event_broker_options & BROKER_HOST_CHECKS)) { gm_log( GM_LOG_ERROR, "mod_gearman needs BROKER_HOST_CHECKS (%i) event_broker_options enabled to work\n", BROKER_HOST_CHECKS ); broker_option_errors++; } if( ( mod_gm_opt->perfdata == GM_ENABLED || mod_gm_opt->servicegroups_num > 0 || mod_gm_opt->services == GM_ENABLED ) && !(event_broker_options & BROKER_SERVICE_CHECKS)) { gm_log( GM_LOG_ERROR, "mod_gearman needs BROKER_SERVICE_CHECKS (%i) event_broker_options enabled to work\n", BROKER_SERVICE_CHECKS ); broker_option_errors++; } if(mod_gm_opt->events == GM_ENABLED && !(event_broker_options & BROKER_EVENT_HANDLERS)) { gm_log( GM_LOG_ERROR, "mod_gearman needs BROKER_EVENT_HANDLERS (%i) event_broker option enabled to work\n", BROKER_EVENT_HANDLERS ); broker_option_errors++; } if(broker_option_errors > 0) return NEB_ERROR; /* check the minimal gearman version */ if((float)atof(gearman_version()) < (float)GM_MIN_LIB_GEARMAN_VERSION) { gm_log( GM_LOG_ERROR, "minimum version of libgearman is %.2f, yours is %.2f\n", (float)GM_MIN_LIB_GEARMAN_VERSION, (float)atof(gearman_version()) ); return NEB_ERROR; } /* init crypto functions */ if(mod_gm_opt->encryption == GM_ENABLED) { if(mod_gm_opt->crypt_key == NULL) { gm_log( GM_LOG_ERROR, "no encryption key provided, please use --key=... or keyfile=...\n"); return NEB_ERROR; } mod_gm_crypt_init(mod_gm_opt->crypt_key); } else { mod_gm_opt->transportmode = GM_ENCODE_ONLY; } /* create client */ if ( create_client( mod_gm_opt->server_list, &client ) != GM_OK ) { gm_log( GM_LOG_ERROR, "cannot start client\n" ); return NEB_ERROR; } /* register callback for process event where everything else starts */ neb_register_callback( NEBCALLBACK_PROCESS_DATA, gearman_module_handle, 0, handle_process_events ); neb_register_callback( NEBCALLBACK_TIMED_EVENT_DATA, gearman_module_handle, 0, handle_timed_events ); /* register export callbacks */ for(i=0;i<GM_NEBTYPESSIZE;i++) { if(mod_gm_opt->exports[i]->elem_number > 0) neb_register_callback( i, gearman_module_handle, 0, handle_export ); } /* log at least one line into the core logfile */ if ( mod_gm_opt->logmode != GM_LOG_MODE_CORE ) { int logmode_saved = mod_gm_opt->logmode; mod_gm_opt->logmode = GM_LOG_MODE_CORE; gm_log( GM_LOG_INFO, "initialized version %s (libgearman %s)\n", GM_VERSION, gearman_version() ); mod_gm_opt->logmode = logmode_saved; } gm_log( GM_LOG_DEBUG, "finished initializing\n" ); return NEB_OK; }
int main (int argc, char **argv, char **env) { struct stat stat_buf; #else int main (int argc, char **argv) { #endif int sid, x; #ifdef EMBEDDEDPERL start_env=env; #endif last_time_increased = 0; /* store the original command line for later reloads */ store_original_comandline(argc, argv); /* * allocate options structure * and parse command line */ mod_gm_opt = gm_malloc(sizeof(mod_gm_opt_t)); set_default_options(mod_gm_opt); if(parse_arguments(argc, argv) != GM_OK) { exit( EXIT_FAILURE ); } #ifdef EMBEDDEDPERL /* make sure the P1 file exists... */ if(p1_file==NULL){ gm_log(GM_LOG_ERROR,"Error: p1.pl file required for embedded Perl interpreter is not set!\n"); exit( EXIT_FAILURE ); } if(stat(p1_file,&stat_buf)!=0){ gm_log(GM_LOG_ERROR,"Error: p1.pl file required for embedded Perl interpreter is missing!\n"); perror("stat"); exit( EXIT_FAILURE ); } #endif /* fork into daemon mode? */ if(mod_gm_opt->daemon_mode == GM_ENABLED) { pid_t pid = fork(); /* an error occurred while trying to fork */ if(pid == -1) { perror("fork"); exit( EXIT_FAILURE ); } /* we are the child process */ else if(pid == 0) { gm_log( GM_LOG_INFO, "mod_gearman worker daemon started with pid %d\n", getpid()); /* Create a new SID for the child process */ sid = setsid(); if ( sid < 0 ) { mod_gm_free_opt(mod_gm_opt); exit( EXIT_FAILURE ); } /* Close out the standard file descriptors */ if(mod_gm_opt->debug_level <= 1) { close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } } /* we are the parent. So forking into daemon mode worked */ else { mod_gm_free_opt(mod_gm_opt); exit( EXIT_SUCCESS ); } } else { gm_log( GM_LOG_INFO, "mod_gearman worker started with pid %d\n", getpid()); } /* print some version information */ gm_log( GM_LOG_DEBUG, "Version %s\n", GM_VERSION ); gm_log( GM_LOG_DEBUG, "running on libgearman %s\n", gearman_version() ); /* set signal handlers for a clean exit */ signal(SIGINT, clean_exit); signal(SIGTERM,clean_exit); signal(SIGHUP, reload_config); signal(SIGPIPE, SIG_IGN); /* check and write pid file */ if(write_pid_file() != GM_OK) { exit(EXIT_FAILURE); } /* init crypto functions */ if(mod_gm_opt->encryption == GM_ENABLED) { mod_gm_crypt_init(mod_gm_opt->crypt_key); } else { mod_gm_opt->transportmode = GM_ENCODE_ONLY; } gm_log( GM_LOG_DEBUG, "main process started\n"); /* start a single non forked standalone worker */ if(mod_gm_opt->debug_level >= 10) { gm_log( GM_LOG_TRACE, "starting standalone worker\n"); #ifdef EMBEDDEDPERL worker_client(GM_WORKER_STANDALONE, 1, shmid, start_env); #else worker_client(GM_WORKER_STANDALONE, 1, shmid); #endif exit(EXIT_SUCCESS); } /* setup shared memory */ setup_child_communicator(); /* start status worker */ make_new_child(GM_WORKER_STATUS); /* setup children */ for(x=0; x < mod_gm_opt->min_worker; x++) { make_new_child(GM_WORKER_MULTI); } /* maintain worker population */ monitor_loop(); gm_log( GM_LOG_ERROR, "worker exited from main loop\n"); clean_exit(15); exit( EXIT_SUCCESS ); }
int main (int argc, char **argv, char **env) { argc = argc; argv = argv; env = env; int rc, rrc; char *result, *error; char cmd[120]; char hostname[GM_BUFFERSIZE]; plan(56); /* set hostname */ gethostname(hostname, GM_BUFFERSIZE-1); /* create options structure and set debug level */ mod_gm_opt = malloc(sizeof(mod_gm_opt_t)); set_default_options(mod_gm_opt); mod_gm_opt->debug_level = 0; #ifdef EMBEDDEDPERL char p1[150]; snprintf(p1, 150, "--p1_file=worker/mod_gearman_p1.pl"); parse_args_line(mod_gm_opt, p1, 0); init_embedded_perl(env); #endif /***************************************** * arg parsing test 1 */ char *args[MAX_CMD_ARGS]; strcpy(cmd, "/bin/hostname"); parse_command_line(cmd, args); like(args[0], cmd, "parsing args cmd 1"); /***************************************** * arg parsing test 2 */ strcpy(cmd, "/bin/cmd blah blub foo"); parse_command_line(cmd,args); like(args[0], "/bin/cmd", "parsing args cmd 2"); like(args[1], "blah", "parsing args cmd 2"); like(args[2], "blub", "parsing args cmd 2"); like(args[3], "foo", "parsing args cmd 2"); /***************************************** * send_gearman */ strcpy(cmd, "./send_gearman --server=blah --key=testtest --host=test --service=test --message=test --returncode=0"); rrc = real_exit_code(run_check(cmd, &result, &error)); //diag(result); cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc); if(atof(gearman_version()) >= 0.31) { like(result, "send_gearman UNKNOWN:", "result"); } else { like(result, "sending job to gearmand failed:", "result"); } free(result); free(error); /***************************************** * send_gearman */ //mod_gm_opt->debug_level = 4; strcpy(cmd, "./send_multi --server=blah --host=blah < t/data/send_multi.txt"); rrc = real_exit_code(run_check(cmd, &result, &error)); //diag(result); cmp_ok(rrc, "==", 3, "cmd '%s' returned rc %d", cmd, rrc); if(atof(gearman_version()) >= 0.31) { like(result, "send_multi UNKNOWN:", "result"); } else { like(result, "sending job to gearmand failed:", "result"); } free(result); free(error); /***************************************** * simple test command 1 */ strcpy(cmd, "/bin/hostname"); rc = run_check(cmd, &result, &error); cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc); rrc = real_exit_code(rc); cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc); free(result); free(error); /***************************************** * simple test command 2 */ strcpy(cmd, "/bin/hostname 2>&1"); rc = run_check(cmd, &result, &error); cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc); rrc = real_exit_code(rc); cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc); free(result); free(error); /***************************************** * simple test command 3 */ strcpy(cmd, "/usr/lib/nagios/plugins/check_icmp -H 127.0.0.1"); rc = run_check(cmd, &result, &error); cmp_ok(rc, "==", 0, "pclose for cmd '%s' returned rc %d", cmd, rc); rrc = real_exit_code(rc); cmp_ok(rrc, "==", 0, "cmd '%s' returned rc %d", cmd, rrc); free(result); free(error); /***************************************** * simple test command 4 */ strcpy(cmd, "echo -n 'test'; exit 2"); rc = run_check(cmd, &result, &error); rrc = real_exit_code(rc); cmp_ok(rrc, "==", 2, "cmd '%s' returned rc %d", cmd, rrc); like(result, "test", "returned result string"); free(result); free(error); gm_job_t * exec_job; exec_job = ( gm_job_t * )malloc( sizeof *exec_job ); set_default_job(exec_job, mod_gm_opt); /***************************************** * non existing command 1 */ exec_job->command_line = strdup("/bin/doesntexist"); exec_job->type = strdup("service"); exec_job->timeout = 10; int fork_on_exec = 0; execute_safe_command(exec_job, fork_on_exec, hostname); cmp_ok(exec_job->return_code, "==", 2, "cmd '%s' returns rc 2", exec_job->command_line); like(exec_job->output, "CRITICAL: Return code of 127 is out of bounds. Make sure the plugin you're trying to run actually exists. \\(worker:", "returned result string"); free(exec_job->output); free(exec_job->error); fork_on_exec = 1; lives_ok({execute_safe_command(exec_job, fork_on_exec, hostname);}, "executing command using fork on exec");