static int get_sensor(const char *name, unsigned flags, AGENT_RESULT *result) { DIR *dir; struct dirent *entries; struct stat buf; char filename[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; double d1,d2,d3; FILE *f; assert(result); init_result(result); dir=opendir("/proc/sys/dev/sensors"); if(NULL == dir) { return SYSINFO_RET_FAIL; } while((entries=readdir(dir))!=NULL) { strscpy(filename,"/proc/sys/dev/sensors/"); zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN); zbx_strlcat(filename,name,MAX_STRING_LEN); if(stat(filename,&buf)==0) { if( NULL == (f = fopen(filename,"r") )) { continue; } fgets(line,MAX_STRING_LEN,f); zbx_fclose(f); if(sscanf(line,"%lf\t%lf\t%lf\n",&d1, &d2, &d3) == 3) { closedir(dir); SET_DBL_RESULT(result, d3); return SYSINFO_RET_OK; } else { closedir(dir); return SYSINFO_RET_FAIL; } } } closedir(dir); return SYSINFO_RET_FAIL; }
/****************************************************************************** * * * Function: zbx_module_docker_up * * * * Purpose: check if container is running * * * * Return value: 1 - is running, 0 - is not running * * * ******************************************************************************/ int zbx_module_docker_up(AGENT_REQUEST *request, AGENT_RESULT *result) { zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_up()"); char *container, *metric; int ret = SYSINFO_RET_FAIL; if (1 != request->nparam) { zabbix_log(LOG_LEVEL_ERR, "Invalid number of parameters: %d", request->nparam); SET_MSG_RESULT(result, strdup("Invalid number of parameters.")); return SYSINFO_RET_FAIL; } if (stat_dir == NULL) { zabbix_log(LOG_LEVEL_DEBUG, "docker.up check is not available at the moment - no stat directory."); SET_MSG_RESULT(result, zbx_strdup(NULL, "docker.up check is not available at the moment - no stat directory.")); return SYSINFO_RET_OK; } container = get_rparam(request, 0); char *stat_file = "/cpuacct.stat"; char *cgroup = "cpuacct/"; size_t filename_size = strlen(base_dir) + strlen(cgroup) + strlen(container) + strlen(stat_dir) + strlen(stat_file) + 2; char *filename = malloc(filename_size); zbx_strlcpy(filename, base_dir, filename_size); zbx_strlcat(filename, cgroup, filename_size); zbx_strlcat(filename, stat_dir, filename_size); zbx_strlcat(filename, container, filename_size); zbx_strlcat(filename, stat_file, filename_size); zabbix_log(LOG_LEVEL_DEBUG, "Metric source file: %s", filename); FILE *file; if (NULL == (file = fopen(filename, "r"))) { zabbix_log(LOG_LEVEL_DEBUG, "Can't open docker container metric file: '%s', container doesn't run", filename); SET_DBL_RESULT(result, 0); return SYSINFO_RET_OK; } zbx_fclose(file); zabbix_log(LOG_LEVEL_DEBUG, "Can open docker container metric file: '%s', container is running", filename); SET_DBL_RESULT(result, 1); return SYSINFO_RET_OK; }
int TCP_LISTEN(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { #ifdef HAVE_PROC FILE *f = NULL; char c[MAX_STRING_LEN]; char porthex[MAX_STRING_LEN]; char pattern[MAX_STRING_LEN]; int ret = SYSINFO_RET_FAIL; assert(result); init_result(result); if(num_param(param) > 1) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, porthex, MAX_STRING_LEN) != 0) { return SYSINFO_RET_FAIL; } strscpy(pattern,porthex); zbx_strlcat(pattern," 00000000:0000 0A", MAX_STRING_LEN); if(NULL == (f = fopen("/proc/net/tcp","r"))) { return SYSINFO_RET_FAIL; } while (NULL != fgets(c,MAX_STRING_LEN,f)) { if(NULL != strstr(c,pattern)) { SET_UI64_RESULT(result, 1); ret = SYSINFO_RET_OK; break; } } zbx_fclose(f); SET_UI64_RESULT(result, 0); return ret; #else return SYSINFO_RET_FAIL; #endif }
int zbx_module_redis_ping(AGENT_REQUEST *request, AGENT_RESULT *result) { char *CONFIG_SOURCE_IP = NULL; zbx_sock_t s; char *rs_host, *str_rs_port; unsigned int rs_port; const char *buf; char rv[MAX_STRING_LEN]; int rs_status = 0; time_t now; char str_time[MAX_STRING_LEN]; char cmd[MAX_STRING_LEN]; char hv[MAX_STRING_LEN]; struct tm *tm = NULL; if (request->nparam == 2) { rs_host = get_rparam(request, 0); str_rs_port = get_rparam(request, 1); rs_port = atoi(str_rs_port); } else if (request->nparam == 1) { rs_host = REDIS_DEFAULT_INSTANCE_HOST; str_rs_port = get_rparam(request, 0); rs_port = atoi(str_rs_port); } else { /* set optional error message */ SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters")); return SYSINFO_RET_FAIL; } /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], args:[%s,%d]", rs_host, rs_port); */ time(&now); tm = localtime(&now); strftime(str_time, MAX_STRING_LEN, "%Y%m%d%H%M%S", tm); /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], str_time:[%s]", str_time); */ zbx_snprintf(cmd, MAX_STRING_LEN, "set ZBX_PING %s\r\nget ZBX_PING\r\nquit\r\n",str_time); zbx_snprintf(hv, MAX_STRING_LEN, "+OK$%d%s+OK", strlen(str_time), str_time); if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, rs_host, rs_port, 0)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], connect to [%s:%d] successful", rs_host, rs_port); */ if (SUCCEED == zbx_tcp_send_raw(&s, cmd)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], send request successful"); */ strscpy(rv, ""); while (NULL != (buf = zbx_tcp_recv_line(&s))) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], get [%s]", buf); */ zbx_strlcat(rv, buf, MAX_STRING_LEN); } /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], all get [%s]", rv); */ if (0 == strcmp(rv, hv)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], redis instance:[%s:%d] is up", rs_host, rs_port); */ rs_status = 1; } } zbx_tcp_close(&s); } if (rs_status == 1) { SET_UI64_RESULT(result, 1); } else { SET_UI64_RESULT(result, 0); } return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: execute_action * * * * Purpose: execute an action depending on mediatype * * * * Parameters: alert - alert details * * mediatype - media details * * * * Return value: SUCCESS - action executed sucessfully * * FAIL - otherwise, error will contain error message * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int execute_action(DB_ALERT *alert,DB_MEDIATYPE *mediatype, char *error, int max_error_len) { int res=FAIL; int pid; char full_path[MAX_STRING_LEN]; char env_alertid[128],env_actionid[128],env_clock[128],env_mediatypeid[128], env_status[128]; char *zbxenv[] = { (char *)&env_alertid, (char *)&env_actionid, (char *)&env_clock, (char *)&env_mediatypeid, (char *)&env_status, (char *)0 }; zabbix_log( LOG_LEVEL_DEBUG, "In execute_action(%s)", mediatype->smtp_server); if(mediatype->type==MEDIA_TYPE_EMAIL) { alarm(40); res = send_email(mediatype->smtp_server,mediatype->smtp_helo,mediatype->smtp_email,alert->sendto,alert->subject, alert->message, error, max_error_len); alarm(0); } #if defined (HAVE_JABBER) else if(mediatype->type==MEDIA_TYPE_JABBER) { /* Jabber uses its own timeouts */ res = send_jabber(mediatype->username, mediatype->passwd, alert->sendto, alert->subject, alert->message, error, max_error_len); } #endif /* HAVE_JABBER */ else if(mediatype->type==MEDIA_TYPE_SMS) { /* SMS uses its own timeouts */ res = send_sms(mediatype->gsm_modem,alert->sendto,alert->message, error, max_error_len); } else if(mediatype->type==MEDIA_TYPE_EXEC) { /* if(-1 == execl(CONFIG_ALERT_SCRIPTS_PATH,mediatype->exec_path,alert->sendto,alert->subject,alert->message))*/ zabbix_log( LOG_LEVEL_DEBUG, "Before execl([%s],[%s])", CONFIG_ALERT_SCRIPTS_PATH, mediatype->exec_path); /* if(-1 == execl("/home/zabbix/bin/lmt.sh","lmt.sh",alert->sendto,alert->subject,alert->message,(char *)0))*/ pid = zbx_fork(); if(0 != pid) { waitpid(pid,NULL,0); } else { strscpy(full_path,CONFIG_ALERT_SCRIPTS_PATH); zbx_strlcat(full_path,"/",MAX_STRING_LEN); zbx_strlcat(full_path,mediatype->exec_path,MAX_STRING_LEN); ltrim_spaces(full_path); zabbix_log( LOG_LEVEL_DEBUG, "Before executing [%s]", full_path); zbx_snprintf(env_alertid,127,"ZABBIX_ALERT_ID=%d", alert->alertid); zbx_snprintf(env_actionid,127,"ZABBIX_ACTION_ID=%d", alert->actionid); zbx_snprintf(env_clock,127,"ZABBIX_ALERT_TIME=%d", alert->clock); zbx_snprintf(env_mediatypeid,127,"ZABBIX_ALERT_MEDIATYPEID=%d", alert->mediatypeid); zbx_snprintf(env_status,127,"ZABBIX_ALERT_STATUS=%d", alert->status); /* if(-1 == execl(full_path,mediatype->exec_path,alert->sendto,alert->subject,alert->message,(char *)0))*/ if(-1 == execle(full_path,mediatype->exec_path,alert->sendto,alert->subject,alert->message,(char *)0, zbxenv)) { zabbix_log( LOG_LEVEL_ERR, "Error executing [%s] [%s]", full_path, strerror(errno)); zabbix_syslog("Error executing [%s] [%s]", full_path, strerror(errno)); zbx_snprintf(error,max_error_len,"Error executing [%s] [%s]", full_path, strerror(errno)); res = FAIL; } else { res = SUCCEED; } /* In normal case the program will never reach this point */ zabbix_log( LOG_LEVEL_DEBUG, "After execl()"); exit(0); } res = SUCCEED; } else { zabbix_log( LOG_LEVEL_ERR, "Unsupported media type [%d] for alert ID [%d]", mediatype->type, alert->alertid); zabbix_syslog("Unsupported media type [%d] for alert ID [%d]", mediatype->type, alert->alertid); zbx_snprintf(error,max_error_len,"Unsupported media type [%d]", mediatype->type); res=FAIL; } zabbix_log( LOG_LEVEL_DEBUG, "End execute_action()"); return res; }
int PROC_NUM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { #if defined(HAVE_PROC_1_STATUS) DIR *dir; struct dirent *entries; struct stat buf; char filename[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char name1[MAX_STRING_LEN]; char name2[MAX_STRING_LEN]; char procname[MAX_STRING_LEN]; char usrname[MAX_STRING_LEN]; char procstat[MAX_STRING_LEN]; int proc_ok = 0; int usr_ok = 0; int stat_ok = 0; struct passwd *usrinfo = NULL; long int lvalue = 0; FILE *f; int proccount = 0; assert(result); init_result(result); if(num_param(param) > 3) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, procname, MAX_STRING_LEN) != 0) { return SYSINFO_RET_FAIL; } if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0) { usrname[0] = 0; } else { if(usrname[0] != 0) { usrinfo = getpwnam(usrname); if(usrinfo == NULL) { /* incorrect user name */ return SYSINFO_RET_FAIL; } } } if(get_param(param, 3, procstat, MAX_STRING_LEN) != 0) { procstat[0] = '\0'; } if(procstat[0] == '\0') { strscpy(procstat, "all"); } if(strcmp(procstat,"run") == 0) { strscpy(procstat,"R"); } else if(strcmp(procstat,"sleep") == 0) { strscpy(procstat,"S"); } else if(strcmp(procstat,"zomb") == 0) { strscpy(procstat,"Z"); } else if(strcmp(procstat,"all") == 0) { procstat[0] = 0; } else { return SYSINFO_RET_FAIL; } dir=opendir("/proc"); if(NULL == dir) { return SYSINFO_RET_FAIL; } while((entries=readdir(dir))!=NULL) { proc_ok = 0; stat_ok = 0; usr_ok = 0; /* Self is a symbolic link. It leads to incorrect results for proc_cnt[zabbix_agentd] */ /* Better approach: check if /proc/x/ is symbolic link */ if(strncmp(entries->d_name,"self",MAX_STRING_LEN) == 0) { continue; } strscpy(filename,"/proc/"); zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN); zbx_strlcat(filename,"/status",MAX_STRING_LEN); if(stat(filename,&buf)==0) { if(NULL == (f = fopen(filename,"r") )) { continue; } if(procname[0] != 0) { fgets(line,MAX_STRING_LEN,f); if(sscanf(line,"%s\t%s\n",name1,name2)==2) { if(strcmp(name1,"Name:") == 0) { if(strcmp(procname,name2)==0) { proc_ok = 1; } } } if(proc_ok == 0) { zbx_fclose(f); continue; } } else { proc_ok = 1; } if(procstat[0] != 0) { while(fgets(line, MAX_STRING_LEN, f) != NULL) { if(sscanf(line, "%s\t%s\n", name1, name2) != 2) { continue; } if(strcmp(name1,"State:") != 0) { continue; } if(strcmp(name2, procstat)) { stat_ok = 1; break; } } } else { stat_ok = 1; } if(usrinfo != NULL) { while(fgets(line, MAX_STRING_LEN, f) != NULL) { if(sscanf(line, "%s\t%li\n", name1, &lvalue) != 2) { continue; } if(strcmp(name1,"Uid:") != 0) { continue; } if(usrinfo->pw_uid == (uid_t)(lvalue)) { usr_ok = 1; break; } } } else { usr_ok = 1; } if(proc_ok && stat_ok && usr_ok) { proccount++; } zbx_fclose(f); } } closedir(dir); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; #else return SYSINFO_RET_FAIL; #endif }
int PROC_MEMORY(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { #if defined(HAVE_PROC_1_STATUS) DIR *dir; struct dirent *entries; struct stat buf; char filename[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char name1[MAX_STRING_LEN]; char name2[MAX_STRING_LEN]; char procname[MAX_STRING_LEN]; char usrname[MAX_STRING_LEN]; char mode[MAX_STRING_LEN]; int proc_ok = 0; int usr_ok = 0; int do_task = DO_SUM; struct passwd *usrinfo = NULL; long long int llvalue = 0; FILE *f; double memsize = -1; int proccount = 0; assert(result); init_result(result); if(num_param(param) > 3) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, procname, MAX_STRING_LEN) != 0) { return SYSINFO_RET_FAIL; } if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0) { usrname[0] = 0; } else { if(usrname[0] != 0) { usrinfo = getpwnam(usrname); if(usrinfo == NULL) { /* incorrect user name */ return SYSINFO_RET_FAIL; } } } if(get_param(param, 3, mode, MAX_STRING_LEN) != 0) { mode[0] = '\0'; } if(mode[0] == '\0') { strscpy(mode, "sum"); } if(strcmp(mode,"avg") == 0) { do_task = DO_AVG; } else if(strcmp(mode,"max") == 0) { do_task = DO_MAX; } else if(strcmp(mode,"min") == 0) { do_task = DO_MIN; } else if(strcmp(mode,"sum") == 0) { do_task = DO_SUM; } else { return SYSINFO_RET_FAIL; } dir=opendir("/proc"); if(NULL == dir) { return SYSINFO_RET_FAIL; } while((entries=readdir(dir))!=NULL) { proc_ok = 0; usr_ok = 0; strscpy(filename,"/proc/"); zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN); zbx_strlcat(filename,"/status",MAX_STRING_LEN); /* Self is a symbolic link. It leads to incorrect results for proc_cnt[zabbix_agentd] */ /* Better approach: check if /proc/x/ is symbolic link */ if(strncmp(entries->d_name,"self",MAX_STRING_LEN) == 0) { continue; } if(stat(filename,&buf)==0) { if(NULL == (f = fopen(filename,"r") )) { continue; } if(procname[0] != 0) { fgets(line,MAX_STRING_LEN,f); if(sscanf(line,"%s\t%s\n",name1,name2)==2) { if(strcmp(name1,"Name:") == 0) { if(strcmp(procname,name2)==0) { proc_ok = 1; } } } if(proc_ok == 0) { zbx_fclose(f); continue; } } else { proc_ok = 1; } if(usrinfo != NULL) { while(fgets(line, MAX_STRING_LEN, f) != NULL) { if(sscanf(line, "%s\t%lli\n", name1, &llvalue) != 2) { continue; } if(strcmp(name1,"Uid:") != 0) { continue; } if(usrinfo->pw_uid == (uid_t)(llvalue)) { usr_ok = 1; break; } } } else { usr_ok = 1; } if(proc_ok && usr_ok) { while(fgets(line, MAX_STRING_LEN, f) != NULL) { if(sscanf(line, "%s\t%lli %s\n", name1, &llvalue, name2) != 3) { continue; } if(strcmp(name1,"VmSize:") != 0) { continue; } proccount++; if(strcasecmp(name2, "kB") == 0) { llvalue <<= 10; } else if(strcasecmp(name2, "mB") == 0) { llvalue <<= 20; } else if(strcasecmp(name2, "GB") == 0) { llvalue <<= 30; } else if(strcasecmp(name2, "TB") == 0) { llvalue <<= 40; } if(memsize < 0) { memsize = (double) llvalue; } else { if(do_task == DO_MAX) { memsize = MAX(memsize, (double) llvalue); } else if(do_task == DO_MIN) { memsize = MIN(memsize, (double) llvalue); } else { memsize += (double) llvalue; } } break; } } zbx_fclose(f); } } closedir(dir); if(memsize < 0) { /* incorrect process name */ memsize = 0; } if(do_task == DO_AVG) { SET_DBL_RESULT(result, proccount == 0 ? 0 : ((double)memsize/(double)proccount)); } else { SET_UI64_RESULT(result, memsize); } return SYSINFO_RET_OK; #else return SYSINFO_RET_FAIL; #endif }
int PROC_MEM(AGENT_REQUEST *request, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char *procname, *proccomm, *param; double memsize = -1; int pgsize = getpagesize(); int proccount = 0, do_task; pid_t curr_pid = getpid(); if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information.")); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "sum")) /* default parameter */ do_task = ZBX_DO_SUM; else if (0 == strcmp(param, "avg")) do_task = ZBX_DO_AVG; else if (0 == strcmp(param, "max")) do_task = ZBX_DO_MAX; else if (0 == strcmp(param, "min")) do_task = ZBX_DO_MIN; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { strscpy(filename, "/proc/"); zbx_strlcat(filename, entries->d_name, MAX_STRING_LEN); if (0 == zbx_stat(filename, &buf)) { proc = open(filename, O_RDONLY); if (-1 == proc) goto lbl_skip_procces; if (-1 == ioctl(proc, PIOCPSINFO, &psinfo)) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc.mem[zabbix_agentd]. */ if (psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if (NULL != procname && '\0' != *procname) if (0 == strcmp(procname, psinfo.pr_fname)) goto lbl_skip_procces; if (NULL != usrinfo) if (usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if (NULL != proccomm && '\0' != *proccomm) if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) goto lbl_skip_procces; proccount++; if (0 > memsize) /* first initialization */ { memsize = (double)(psinfo.pr_rssize * pgsize); } else { if (ZBX_DO_MAX == do_task) memsize = MAX(memsize, (double)(psinfo.pr_rssize * pgsize)); else if (ZBX_DO_MIN == do_task) memsize = MIN(memsize, (double)(psinfo.pr_rssize * pgsize)); else /* SUM */ memsize += (double)(psinfo.pr_rssize * pgsize); } lbl_skip_procces: if (-1 != proc) close(proc); } } closedir(dir); if (0 > memsize) { /* incorrect process name */ memsize = 0; } if (ZBX_DO_AVG == do_task) SET_DBL_RESULT(result, 0 == proccount ? 0 : memsize / (double)proccount); else SET_UI64_RESULT(result, memsize); return SYSINFO_RET_OK; }
int PROC_NUM(AGENT_REQUEST *request, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; zbx_stat_t buf; struct passwd *usrinfo; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char *procname, *proccomm, *param; int proccount = 0, zbx_proc_stat; pid_t curr_pid = getpid(); if (4 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } procname = get_rparam(request, 0); param = get_rparam(request, 1); if (NULL != param && '\0' != *param) { if (NULL == (usrinfo = getpwnam(param))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain user information.")); return SYSINFO_RET_FAIL; } } else usrinfo = NULL; param = get_rparam(request, 2); if (NULL == param || '\0' == *param || 0 == strcmp(param, "all")) zbx_proc_stat = -1; else if (0 == strcmp(param, "run")) zbx_proc_stat = PR_SRUN; else if (0 == strcmp(param, "sleep")) zbx_proc_stat = PR_SSLEEP; else if (0 == strcmp(param, "zomb")) zbx_proc_stat = PR_SZOMB; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } proccomm = get_rparam(request, 3); if (NULL == (dir = opendir("/proc"))) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot open /proc: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } while (NULL != (entries = readdir(dir))) { strscpy(filename, "/proc/"); zbx_strlcat(filename, entries->d_name,MAX_STRING_LEN); if (0 == zbx_stat(filename, &buf)) { proc = open(filename, O_RDONLY); if (-1 == proc) goto lbl_skip_procces; if (-1 == ioctl(proc, PIOCPSINFO, &psinfo)) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc.num[zabbix_agentd]. */ if (psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if (NULL != procname && '\0' != *procname) if (0 != strcmp(procname, psinfo.pr_fname)) goto lbl_skip_procces; if (NULL != usrinfo) if (usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if (-1 != zbx_proc_stat) if (psinfo.pr_sname != zbx_proc_stat) goto lbl_skip_procces; if (NULL != proccomm && '\0' != *proccomm) if (NULL == zbx_regexp_match(psinfo.pr_psargs, proccomm, NULL)) goto lbl_skip_procces; proccount++; lbl_skip_procces: if (-1 != proc) close(proc); } } closedir(dir); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
int PROC_MEM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; struct stat buf; struct passwd *usrinfo = NULL; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char procname[MAX_STRING_LEN]; char usrname[MAX_STRING_LEN]; char mode[MAX_STRING_LEN]; char proccomm[MAX_STRING_LEN]; int do_task = DO_SUM; double memsize = -1; int pgsize = getpagesize(); int proccount = 0; pid_t curr_pid = getpid(); if(num_param(param) > 4) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, procname, MAX_STRING_LEN) != 0) { return SYSINFO_RET_FAIL; } if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0) { usrname[0] = 0; } else { if(usrname[0] != 0) { usrinfo = getpwnam(usrname); if(usrinfo == NULL) { /* incorrect user name */ return SYSINFO_RET_FAIL; } } } if(get_param(param, 3, mode, MAX_STRING_LEN) != 0) { mode[0] = '\0'; } if(mode[0] == '\0') { strscpy(mode, "sum"); } if(strcmp(mode,"avg") == 0) { do_task = DO_AVG; } else if(strcmp(mode,"max") == 0) { do_task = DO_MAX; } else if(strcmp(mode,"min") == 0) { do_task = DO_MIN; } else if(strcmp(mode,"sum") == 0) { do_task = DO_SUM; } else { return SYSINFO_RET_FAIL; } if(get_param(param, 4, proccomm, MAX_STRING_LEN) != 0) { proccomm[0] = '\0'; } dir=opendir("/proc"); if(NULL == dir) { return SYSINFO_RET_FAIL; } while((entries=readdir(dir))!=NULL) { strscpy(filename,"/proc/"); zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN); if(stat(filename,&buf)==0) { proc = open(filename,O_RDONLY); if(proc == -1) goto lbl_skip_procces; if(ioctl(proc,PIOCPSINFO,&psinfo) == -1) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc_cnt[zabbix_agentd] */ if(psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if(procname[0] != 0) if(strcmp(procname,psinfo.pr_fname) != 0) goto lbl_skip_procces; if(usrinfo != NULL) if(usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if(proccomm[0] != '\0') if(zbx_regexp_match(psinfo.pr_psargs,proccomm,NULL) == NULL) goto lbl_skip_procces; proccount++; if(memsize < 0) /* First inicialization */ { memsize = (double) (psinfo.pr_rssize * pgsize); } else { if(do_task == DO_MAX) { memsize = MAX(memsize, (double) (psinfo.pr_rssize * pgsize)); } else if(do_task == DO_MIN) { memsize = MIN(memsize, (double) (psinfo.pr_rssize * pgsize)); } else /* SUM */ { memsize += (double) (psinfo.pr_rssize * pgsize); } } lbl_skip_procces: if(proc) close(proc); } } closedir(dir); if(memsize < 0) { /* incorrect process name */ memsize = 0; } if(do_task == DO_AVG) { SET_DBL_RESULT(result, proccount == 0 ? 0 : ((double)memsize/(double)proccount)); } else { SET_UI64_RESULT(result, memsize); } return SYSINFO_RET_OK; }
int PROC_NUM(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { DIR *dir; int proc; struct dirent *entries; struct stat buf; struct passwd *usrinfo = NULL; struct prpsinfo psinfo; char filename[MAX_STRING_LEN]; char procname[MAX_STRING_LEN]; char usrname[MAX_STRING_LEN]; char procstat[MAX_STRING_LEN]; char proccomm[MAX_STRING_LEN]; int do_task = DO_SUM; int proccount = 0; pid_t curr_pid = getpid(); if(num_param(param) > 4) { return SYSINFO_RET_FAIL; } if(get_param(param, 1, procname, MAX_STRING_LEN) != 0) { return SYSINFO_RET_FAIL; } if(get_param(param, 2, usrname, MAX_STRING_LEN) != 0) { usrname[0] = 0; } else { if(usrname[0] != 0) { usrinfo = getpwnam(usrname); if(usrinfo == NULL) { /* incorrect user name */ return SYSINFO_RET_FAIL; } } } if(get_param(param, 3, procstat, MAX_STRING_LEN) != 0) { procstat[0] = '\0'; } if(procstat[0] == '\0') { strscpy(procstat, "all"); } if(strcmp(procstat,"run") == 0) { procstat[0] = PR_SRUN; procstat[1] = '\0'; } else if(strcmp(procstat,"sleep") == 0) { procstat[0] = PR_SSLEEP; procstat[1] = '\0'; } else if(strcmp(procstat,"zomb") == 0) { procstat[0] = PR_SZOMB; procstat[1] = '\0'; } else if(strcmp(procstat,"all") == 0) { procstat[0] = '\0'; } else { return SYSINFO_RET_FAIL; } if(get_param(param, 4, proccomm, MAX_STRING_LEN) != 0) { proccomm[0] = '\0'; } dir=opendir("/proc"); if(NULL == dir) { return SYSINFO_RET_FAIL; } while((entries=readdir(dir))!=NULL) { strscpy(filename,"/proc/"); zbx_strlcat(filename,entries->d_name,MAX_STRING_LEN); if(stat(filename,&buf)==0) { proc = open(filename,O_RDONLY); if(proc == -1) goto lbl_skip_procces; if(ioctl(proc,PIOCPSINFO,&psinfo) == -1) goto lbl_skip_procces; /* Self process information. It leads to incorrect results for proc_cnt[zabbix_agentd] */ if(psinfo.pr_pid == curr_pid) goto lbl_skip_procces; if(procname[0] != 0) if(strcmp(procname,psinfo.pr_fname) != 0) goto lbl_skip_procces; if(usrinfo != NULL) if(usrinfo->pw_uid != psinfo.pr_uid) goto lbl_skip_procces; if(procstat[0] != '\0') if(psinfo.pr_sname != procstat[0]) goto lbl_skip_procces; if(proccomm[0] != '\0') if(zbx_regexp_match(psinfo.pr_psargs,proccomm,NULL) == NULL) goto lbl_skip_procces; proccount++; lbl_skip_procces: if(proc) close(proc); } } closedir(dir); SET_UI64_RESULT(result, proccount); return SYSINFO_RET_OK; }
/* * Connect to the database. * If fails, program terminates. */ int zbx_db_connect(char *host, char *user, char *password, char *dbname, char *dbsocket, int port) { int ret = ZBX_DB_OK; #ifdef HAVE_SQLITE3 char *p, *path; #endif /* HAVE_SQLITE3 */ #ifdef HAVE_MYSQL /* For MySQL >3.22.00 */ /* if( ! mysql_connect( conn, NULL, dbuser, dbpassword ) )*/ conn = mysql_init(NULL); if (!mysql_real_connect(conn, host, user, password, dbname, port, dbsocket, CLIENT_MULTI_STATEMENTS)) { zabbix_errlog(ERR_Z3001, dbname, mysql_errno(conn), mysql_error(conn)); ret = ZBX_DB_FAIL; } if (ZBX_DB_OK == ret) { if (0 != mysql_select_db(conn, dbname)) { zabbix_errlog(ERR_Z3001, dbname, mysql_errno(conn), mysql_error(conn)); ret = ZBX_DB_FAIL; } } if (ZBX_DB_OK == ret) DBexecute("SET CHARACTER SET utf8"); if (ZBX_DB_FAIL == ret) { switch (mysql_errno(conn)) { case CR_CONN_HOST_ERROR: case CR_SERVER_GONE_ERROR: case CR_CONNECTION_ERROR: case CR_SERVER_LOST: case ER_SERVER_SHUTDOWN: case ER_UNKNOWN_ERROR: ret = ZBX_DB_DOWN; break; default: break; } } return ret; #endif #ifdef HAVE_POSTGRESQL char *cport = NULL; DB_RESULT result; DB_ROW row; int sversion; if( port ) cport = zbx_dsprintf(cport, "%i", port); conn = PQsetdbLogin(host, cport, NULL, NULL, dbname, user, password ); zbx_free(cport); /* check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { zabbix_errlog(ERR_Z3001, dbname, 0, PQerrorMessage(conn)); ret = ZBX_DB_FAIL; } result = DBselect("select oid from pg_type where typname = 'bytea'"); row = DBfetch(result); if(row) { ZBX_PG_BYTEAOID = atoi(row[0]); } DBfree_result(result); #ifdef HAVE_FUNCTION_PQSERVERVERSION sversion = PQserverVersion(conn); zabbix_log(LOG_LEVEL_DEBUG, "PostgreSQL Server version: %d", sversion); #else sversion = 0; #endif /* HAVE_FUNCTION_PQSERVERVERSION */ if (sversion >= 80100) { /* disable "nonstandard use of \' in a string literal" warning */ DBexecute("set escape_string_warning to off"); } return ret; #endif #ifdef HAVE_ORACLE char connect[MAX_STRING_LEN]; zbx_strlcpy(connect, user, sizeof(connect)); if (password && *password) { zbx_strlcat(connect, "/", sizeof(connect)); zbx_strlcat(connect, password, sizeof(connect)); if (dbname && *dbname) { zbx_strlcat(connect, "@", sizeof(connect)); zbx_strlcat(connect, dbname, sizeof(connect)); } } if (SQLO_SUCCESS != sqlo_init(SQLO_OFF, 1, 100)) { zabbix_errlog(ERR_Z3001, connect, 0, "Failed to init libsqlora8"); ret = ZBX_DB_FAIL; } if (ZBX_DB_OK == ret) { /* login */ /* TODO: how to use port??? */ if (SQLO_SUCCESS != sqlo_connect(&oracle, connect)) { zabbix_errlog(ERR_Z3001, connect, 0, "sqlo_connect"); ret = ZBX_DB_FAIL; } } if (ZBX_DB_OK == ret) sqlo_autocommit_off(oracle); return ret; #endif #ifdef HAVE_SQLITE3 /* check to see that the backend connection was successfully made */ if (SQLITE_OK != (ret = sqlite3_open(dbname, &conn))) { zabbix_errlog(ERR_Z3001, dbname, 0, sqlite3_errmsg(conn)); exit(FAIL); } /* Do not return SQLITE_BUSY immediately, wait for N ms */ sqlite3_busy_timeout(conn, 60*1000); sqlite_transaction_started = 0; path = strdup(dbname); if (NULL != (p = strrchr(path, '/'))) *++p = '\0'; else *path = '\0'; DBexecute("PRAGMA synchronous = 0"); /* OFF */ DBexecute("PRAGMA temp_store = 2"); /* MEMORY */ DBexecute("PRAGMA temp_store_directory = '%s'", path); zbx_free(path); return ret; #endif }
/****************************************************************************** * * * Function: zbx_module_docker_discovery * * * * Purpose: container discovery * * * * Return value: SYSINFO_RET_FAIL - function failed, item will be marked * * as not supported by zabbix * * SYSINFO_RET_OK - success * * * ******************************************************************************/ int zbx_module_docker_discovery(AGENT_REQUEST *request, AGENT_RESULT *result) { #include "zbxjson.h" zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_discovery()"); struct zbx_json j; if (stat_dir == NULL && zbx_docker_stat_detect() == SYSINFO_RET_FAIL) { zabbix_log(LOG_LEVEL_DEBUG, "docker.discovery is not available at the moment - no stat directory - empty discovery"); zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); zbx_json_close(&j); SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer)); zbx_json_free(&j); return SYSINFO_RET_OK; } char line[MAX_STRING_LEN], *p, *mpoint, *mtype, container; FILE *f; DIR *dir; zbx_stat_t sb; char *file = NULL; struct dirent *d; char *cgroup = "cpuacct/"; size_t ddir_size = strlen(base_dir) + strlen(cgroup) + strlen(stat_dir) + 2; char *ddir = malloc(ddir_size); zbx_strlcpy(ddir, base_dir, ddir_size); zbx_strlcat(ddir, cgroup, ddir_size); zbx_strlcat(ddir, stat_dir, ddir_size); if (NULL == (dir = opendir(ddir))) { zbx_error("%s: %s\n", ddir, zbx_strerror(errno)); } zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); char scontainerid[13]; while (NULL != (d = readdir(dir))) { if(0 == strcmp(d->d_name, ".") || 0 == strcmp(d->d_name, "..")) continue; file = zbx_dsprintf(file, "%s/%s", ddir, d->d_name); if (0 != zbx_stat(file, &sb) || 0 == S_ISDIR(sb.st_mode)) continue; zbx_json_addobject(&j, NULL); zbx_json_addstring(&j, "{#FCONTAINERID}", d->d_name, ZBX_JSON_TYPE_STRING); zbx_strlcpy(scontainerid, d->d_name, 13); zbx_json_addstring(&j, "{#SCONTAINERID}", scontainerid, ZBX_JSON_TYPE_STRING); zbx_json_close(&j); } if (0 != closedir(dir)) { zbx_error("%s: %s\n", ddir, zbx_strerror(errno)); } zbx_json_close(&j); SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer)); zbx_json_free(&j); return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: zbx_module_docker_mem * * * * Purpose: container memory metrics * * * * Return value: SYSINFO_RET_FAIL - function failed, item will be marked * * as not supported by zabbix * * SYSINFO_RET_OK - success * * * ******************************************************************************/ int zbx_module_docker_mem(AGENT_REQUEST *request, AGENT_RESULT *result) { // documentation https://www.kernel.org/doc/Documentation/cgroups/memory.txt zabbix_log(LOG_LEVEL_DEBUG, "In zbx_module_docker_mem()"); char *container, *metric; int ret = SYSINFO_RET_FAIL; if (2 != request->nparam) { zabbix_log(LOG_LEVEL_ERR, "Invalid number of parameters: %d", request->nparam); SET_MSG_RESULT(result, strdup("Invalid number of parameters.")); return SYSINFO_RET_FAIL; } if (stat_dir == NULL) { zabbix_log(LOG_LEVEL_DEBUG, "docker.cpu metrics are not available at the moment - no stat directory."); SET_MSG_RESULT(result, zbx_strdup(NULL, "docker.cpu metrics are not available at the moment - no stat directory.")); return SYSINFO_RET_OK; } container = get_rparam(request, 0); metric = get_rparam(request, 1); char *stat_file = "/memory.stat"; char *cgroup = "memory/"; size_t filename_size = strlen(base_dir) + strlen(cgroup) + strlen(container) + strlen(stat_dir) + strlen(stat_file) + 2; char *filename = malloc(filename_size); zbx_strlcpy(filename, base_dir, filename_size); zbx_strlcat(filename, cgroup, filename_size); zbx_strlcat(filename, stat_dir, filename_size); zbx_strlcat(filename, container, filename_size); zbx_strlcat(filename, stat_file, filename_size); zabbix_log(LOG_LEVEL_DEBUG, "Metric source file: %s", filename); FILE *file; if (NULL == (file = fopen(filename, "r"))) { zabbix_log(LOG_LEVEL_ERR, "Can't open docker container metric file: '%s'", filename); SET_MSG_RESULT(result, strdup("Can't open docker container memory.stat file")); return SYSINFO_RET_FAIL; } char line[MAX_STRING_LEN]; char *metric2 = malloc(strlen(metric)+1); memcpy(metric2, metric, strlen(metric)); memcpy(metric2 + strlen(metric), " ", 2); zbx_uint64_t value = 0; zabbix_log(LOG_LEVEL_DEBUG, "Looking metric %s in memory.stat file", metric); while (NULL != fgets(line, sizeof(line), file)) { if (0 != strncmp(line, metric2, strlen(metric2))) continue; // aaa if (1 != sscanf(line, "%*s " ZBX_FS_UI64, &value)) { zabbix_log(LOG_LEVEL_ERR, "sscanf failed for matched metric line"); continue; } // production severity only DEBUG zabbix_log(LOG_LEVEL_DEBUG, "Container: %s; metric: %s; value: %d", container, metric, value); SET_UI64_RESULT(result, value); ret = SYSINFO_RET_OK; break; } zbx_fclose(file); if (SYSINFO_RET_FAIL == ret) SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot find a line with requested metric in docker container memory.stat file.")); return ret; }