📄 monsvrd.c
字号:
/* * This is the client of cluster monitor. * It is a daemon. * * Copyright (c) 2004, by: Jian Shen * All rights reserved. Peking University, China * <shenjian@net.pku.edu.cn> * * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <getopt.h>#include <signal.h>#include <pthread.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/utsname.h>#include <arpa/inet.h>#include <netinet/in.h>#include "statinfo.h"#include "monitor.h"#include "svr_common.h"#include "util.h"#include "config.h"#include "netif.h"#define SVRNAME "sysmon"#define RUN_AS_DAEMON 1#define MOREINFO//#define CLT_DEBUGstatic char MONPID_FILE[50];static void* reply(void* arg);static void* waitsvr(void* arg);static void help(){ printf("\nSystem load monitor daemon.\n"); printf("usage: \n"); printf("\t monsvrd [options|stop] [server_address]\n"); printf("\t -h|--help\n"); printf("\t -t|--time seconds \t specify time interval to send load info to collector\n"); printf("\t -b|--broadcast \t use broadcast address\n"); printf("\t -i|--interface \t specify network interface\n"); printf("examples:\n"); printf("\t sysmon 192.168.0.1\n"); printf("\t sysmon -t 2 192.168.0.1\n"); printf("\t sysmon -b\n"); printf("\t sysmon -b -i eth0\n"); printf("\t sysmon stop\n"); printf("\nreport bugs to <shenjian@net.pku.edu.cn>.\n"); printf("\n");}static void usage(){ printf("usage: \n"); printf("\t monsvrd [options|stop] [server_address]\n"); printf("\t -h|--help\n"); printf("\t -t|--time seconds \t specify time interval to send load info to collector\n"); printf("\t -b|--broadcast \t use broadcast address\n"); printf("\t -i|--interface \t specify network interface\n"); printf("\n");}static int to_exit = 0;static pthread_t thr;static void terminate(int sig){ to_exit = 1; if(pthread_cancel(thr) !=0) fprintf(stderr, "pthread_cancel failed.\n");}/*********************** * PUSH ***********************/extern struct netif if_table[4];void get_sysload(system_load_info* sysload){ int i; /* get system load */ get_cpu_utilization(); get_load_average(); get_free_memory(); /* packaging */ sysload->num_of_cpu = mon_cpu_count; for(i=0; i<mon_cpu_count; i++) { sprintf(sysload->cpu_freq[i], "%.3f", mon_cpu_freq[i]); sprintf(sysload->cpu_util[i], "%.1f", mon_cpu_util[i]*100); } sysload->total_mem = mon_total_mem; sysload->free_mem = mon_free_mem; for(i=0; i<3; i++) { sprintf(sysload->loadavg[i], "%.2f", mon_load_avg[i]); } uname(&sysload->sysinfo);// print_load(sysload);}int main(int argc, char* argv[]){ struct sockaddr_in saddr; int server_sock; int rv; int svr_pid; struct sigaction sa; system_load_info* sysload; /******************************** * deal with options ********************************/ int time_interval = 3; /* time interval to send load message to collector, default is 3 seconds */ int BROADCAST = 0; /* default: do not use broadcast address. */ int NETINTF = 0; /* default: get network interface automatically, NETINTF=1 if given by augument */ int argcnt = argc; char** program = argv; int next_opt; char* target_ip; /* target ip address */ char net_intf[20]; /* network interface */ const char* short_options = "ht:bi:"; const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"time", 1, NULL, 't'}, {"broadcast", 0, NULL, 'b'}, {"interface", 1, NULL, 'i'} }; do{ next_opt = getopt_long(argc, argv, short_options, long_options, NULL); argcnt --; switch(next_opt) { case 'h' : /* -h or --help */ help(); exit(1); case 't' : /* -t or --time */ time_interval = atoi(optarg); program += 2; argcnt --; break; case 'b' : /* -b or --broadcast */ BROADCAST = 1; program += 1; break; case 'i' : /* -i or --interface */ NETINTF = 1; strcpy(net_intf, optarg); program += 2; argcnt --; break; case '?' : /* invalid option */ usage(); exit(1); case -1 : /* end of option list */ break; } }while(next_opt != -1); if(!BROADCAST) { if(argcnt != 1) { printf("Missing command or server ip.\n"); usage(); exit(1); } }else { if(argcnt != 0) { usage(); exit(1); } } /* get user name */ sprintf(MONPID_FILE, "/tmp/sysmon-%s.pid", get_user_name()); if(!BROADCAST && strcmp(program[1], "stop") == 0 ) { /* stop daemon */ svr_pid = check_proc_running(MONPID_FILE, SVRNAME); if(svr_pid < 0) exit(1); printf("monitor daemon stop...\n"); if(kill(svr_pid, SIGUSR1) < 0) { perror("kill"); exit(1); } exit(0); }else { /* start server */#if RUN_AS_DAEMON /* start server as a daemon */ daemon_init();#endif /* check this is the only process entity running */ check_single_on(MONPID_FILE, SVRNAME); if(BROADCAST) { if(!NETINTF) { int netif_cnt = get_netif(); if(netif_cnt > 1) { printf("There is more than one network interface on this machine:\n"); int i; for(i=0; i<netif_cnt; i++) { struct sockaddr_in* addr = (struct sockaddr_in*)&if_table[i].ipaddr; printf("\t%s : %s\n", if_table[i].name, inet_ntoa(addr->sin_addr)); } printf("You should specify network interface like this:\n"); printf("\tsysmon -b -i interface_name\n"); exit(0); } }else { if(get_if_addr(net_intf, &if_table[0]) < 0) { fprintf(stderr, "Can not recognize network interface: %s\n", net_intf); exit(1); } } } printf("monitor daemon start...\n");#if RUN_AS_DAEMON /* set daemon to have no tty */ daemon_notty();#endif } /* install SIGKILL handler */ bzero(&sa, sizeof(sa)); sa.sa_handler = terminate; if (sigaction(SIGUSR1, &sa, NULL) <0 ) { perror("sigaction SIGUSR1"); exit(1); } /* Ctrl+C */ if (sigaction(SIGINT, &sa, NULL) <0 ) { perror("sigaction SIGINT"); exit(1); } if(!BROADCAST) { /* get host's ip address */ target_ip = get_host_ip(program[1]); if(target_ip == NULL) { fprintf(stderr, "No such host: %s.\n", program[1]); exit(1); } bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; inet_aton(target_ip, &(saddr.sin_addr)); /* target_ip should be a broadcast address */ saddr.sin_port = htons(SVRPORT);#ifdef CLT_DEBUG printf("server: %s\n", inet_ntoa(saddr.sin_addr));#endif if((server_sock = socket(AF_INET, SOCK_DGRAM, 0)) <0) { perror("socket"); exit(1); } }else { bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr = ((struct sockaddr_in*)&if_table[0].broadaddr)->sin_addr; saddr.sin_port = htons(SVRPORT);#ifdef CLT_DEBUG printf("server: %s\n", inet_ntoa(saddr.sin_addr));#endif if((server_sock = socket(AF_INET, SOCK_DGRAM, 0)) <0) { perror("socket"); exit(1); } const int on = 1; if(setsockopt(server_sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { perror("setsockopt SO_BROADCAST"); exit(1); } } /**************************** * initialize system monitor ****************************/ monitor_init();#ifdef MOREINFO /************************************************** * create thread to interact with monitoring client ***************************************************/ if(pthread_create(&thr, NULL, (void *)waitsvr, NULL) != 0) { fprintf(stderr, "pthread_create fails.\n"); close(server_sock); monitor_cleanup(); exit(1); }#endif /*************************** * monitoring ***************************/ while(!to_exit) { sleep(time_interval); if(to_exit) break; sysload = (system_load_info*)malloc(sizeof(system_load_info)); if(sysload == NULL) continue; get_sysload(sysload); /* send load packet */ rv = sendto(server_sock, sysload, sizeof(system_load_info), 0, (struct sockaddr*)&saddr, sizeof(struct sockaddr)); if(rv < 0) perror("sendto"); free(sysload); sysload = NULL; } monitor_cleanup(); close(server_sock); unlink(MONPID_FILE);/* if(pthread_join(thr, NULL) != 0) *//* fprintf(stderr, "pthread_join fails.\n"); */ return 0;}/************** * PULL *************//* thread to wait for ps request */static void* waitsvr(void* arg){ struct sockaddr_in saddr, caddr; int svrfd, cltfd; int rv, len, optval; fd_set fds; pthread_t reply_thr; pthread_attr_t reply_thr_attr; /* initialize thread attribute */ if(pthread_attr_init(&reply_thr_attr) !=0) fprintf(stderr, "pthread_attr_init failed.\n"); /* set thread to detached */ if(pthread_attr_setdetachstate(&reply_thr_attr, PTHREAD_CREATE_DETACHED) !=0) fprintf(stderr, "pthread_attr_setdetachstate failed.\n"); /* make up server address */ bzero(&saddr, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(MONPORT); if((svrfd = socket(AF_INET, SOCK_STREAM, 0)) <0) { perror("socket"); exit(1); } if (setsockopt(svrfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) <0 ) { perror("setsockopt"); exit(1); } if (bind(svrfd, (struct sockaddr *) &saddr, sizeof(saddr)) <0 ) { perror("bind"); exit(1); } if (listen(svrfd, 5) <0 ) { perror("listen"); exit(1); } while (1) { /* wait for connections */ FD_ZERO(&fds); FD_SET(svrfd, &fds); rv = select(svrfd+1, &fds, NULL, NULL, NULL); if (rv < 0 && errno == EINTR) continue; if (rv < 0) { perror("select"); exit(1); } len = sizeof(struct sockaddr); cltfd = accept(svrfd, (struct sockaddr *) &caddr, &len); if (cltfd <0 ) { perror("accept"); continue; } /**************************** * create reply thread ****************************/ if(pthread_create(&reply_thr, &reply_thr_attr, (void *)reply, &cltfd) != 0) { fprintf(stderr, "pthread_create fails.\n"); close(svrfd); exit(1); } }}/* thread to send back system information */static void* reply(void* arg){ proc_list_t* plist; struct load_request req; struct load_reply err_rep; int rv; int client_sock = *((int*)arg); err_rep.result = -1; bzero(&req, sizeof(struct load_request)); rv = recv(client_sock, &req, sizeof(struct load_request), MSG_WAITALL); if(rv == 0) { goto out; /* remote host close the connection */ } switch(req.type) { case PROCLIST:#ifdef CLT_DEBUG fprintf(stderr, "PROCLIST\n");#endif plist = get_proc_list(); if(plist == NULL) { send(client_sock, &err_rep, sizeof(struct load_reply), 0); break; } send(client_sock, plist, sizeof(proc_list_t), 0); free(plist); plist = NULL; break; default: send(client_sock, &err_rep, sizeof(struct load_reply), 0); break; } out: close(client_sock); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -