#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 255 #endif #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) struct network_info { struct timespec check_time; u_long inbound_packets; u_long outbound_packets; u_long inbound_bytes; u_long outbound_bytes; }; struct fhs_info { char hostname[HOST_NAME_MAX + 1]; double load_avg[3]; float cpu_stat[CPUSTATES]; int memory_total; // MByte int memory_stat[6]; // MByte int swap_stat[6]; // Size MByte, in/out : KByte struct network_info network_old; struct network_info network_now; }; static void getsysctl(const char *name, void *ptr, size_t len) { size_t nlen = len; if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) { fprintf(stderr, "sysctl(%s...) failed: %s\n", name, strerror(errno)); //quit(23); } if (nlen != len) { fprintf(stderr, "sysctl(%s...) expected %lu byte, got %lu byte\n", name, (unsigned long)len, (unsigned long)nlen); //quit(23); } return; } long percentages(int cnt, int * out, register long * new, register long * old, long * diffs) { register int i; register long change; register long total_change; register long *dp; long half_total; /* initialization */ total_change = 0; dp = diffs; /* calculate changes for each state and the overall change */ for (i = 0; i < cnt; i++) { if ((change = *new - *old) < 0) { /* this only happens when the counter wraps */ change = (int) ((unsigned long)*new-(unsigned long)*old); } total_change += (*dp++ = change); *old++ = *new++; } /* avoid divide by zero potential */ if (total_change == 0) { total_change = 1; } /* calculate percentages based on overall change, rounding up */ half_total = total_change / 2l; /* Do not divide by 0. Causes Floating point exception */ if(total_change) { for (i = 0; i < cnt; i++) { *out++ = (int)((*diffs++ * 1000 + half_total) / total_change); } } /* return the total in case the caller wants to use it */ return(total_change); } bool get_loadavg( struct fhs_info * fhs) { int i = 0; struct loadavg sysload; GETSYSCTL("vm.loadavg", sysload); //getsysctl("vm.loadavg", &sysload, sizeof(sysload)); for (i = 0; i < 3; i++) { fhs->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale; } return true; } static long cp_time[CPUSTATES]; static long cp_old[CPUSTATES]; static long cp_diff[CPUSTATES]; bool get_cpuusage( struct fhs_info * fhs ) { int i; int cpu_stat[CPUSTATES]; GETSYSCTL("kern.cp_time", cp_time); percentages(CPUSTATES, cpu_stat, cp_time, cp_old, cp_diff); for( i = 0; i < CPUSTATES; i++) { if( cpu_stat[i] >= 1000) fhs->cpu_stat[i] = 100.0; else fhs->cpu_stat[i] = ((float)cpu_stat[i])/10.0; } return true; } static int pageshift; /* log base 2 of the pagesize */ #define pagetok(size) ((size) << pageshift) bool get_memory( struct fhs_info * fhs ) { long memory_total; int memory_stat[6]; long bufspace = 0; GETSYSCTL("hw.physmem", memory_total); GETSYSCTL("vfs.bufspace", bufspace); GETSYSCTL("vm.stats.vm.v_active_count", memory_stat[0]); GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stat[1]); GETSYSCTL("vm.stats.vm.v_wire_count", memory_stat[2]); GETSYSCTL("vm.stats.vm.v_cache_count", memory_stat[3]); GETSYSCTL("vm.stats.vm.v_free_count", memory_stat[5]); // byte -> Mbyte fhs->memory_total = memory_total /1024/1024; /* convert memory stats to Kbytes -> Mbytes: +512/1024 -> round() */ fhs->memory_stat[0] = ( pagetok(memory_stat[0]) + 512 ) /1024; fhs->memory_stat[1] = ( pagetok(memory_stat[1]) + 512 ) /1024; fhs->memory_stat[2] = ( pagetok(memory_stat[2]) + 512 ) /1024; fhs->memory_stat[3] = ( pagetok(memory_stat[3]) + 512 ) /1024; fhs->memory_stat[4] = (( bufspace / 1024) + 512 ) /1024; fhs->memory_stat[5] = ( pagetok(memory_stat[5]) + 512 ) /1024; return true;; } #include #include static kvm_t *kd; static int swapmode(int *retavail, int *retfree) { int n; int pagesize = getpagesize(); struct kvm_swap swapary[1]; *retavail = 0; *retfree = 0; #define CONVERT(v) ((quad_t)(v) * pagesize / 1024) n = kvm_getswapinfo(kd, swapary, 1, 0); if (n < 0 || swapary[0].ksw_total == 0) return (0); *retavail = CONVERT(swapary[0].ksw_total); *retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used); n = (int)(swapary[0].ksw_used * 100.0 / swapary[0].ksw_total); return (n); } static int swappgsin = -1; static int swappgsout = -1; static unsigned int swap_delay = 0; static int swapavail = 0; static int swapfree = 0; bool get_swap(struct fhs_info * fhs) { int nspgsin, nspgsout; GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin); GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout); // first interval if (swappgsin < 0) { fhs->swap_stat[4] = 0; fhs->swap_stat[5] = 0; } // compute differences between old and new swap statistic else { fhs->swap_stat[4] = pagetok(((nspgsin - swappgsin))); fhs->swap_stat[5] = pagetok(((nspgsout - swappgsout))); } swappgsin = nspgsin; swappgsout = nspgsout; // call CPU heavy swapmode() only for changes if (fhs->swap_stat[4] > 0 || fhs->swap_stat[5] > 0 || swap_delay == 0) { fhs->swap_stat[3] = swapmode(&swapavail, &swapfree); fhs->swap_stat[0] = ( swapavail + 512 ) / 1024; fhs->swap_stat[1] = ( swapavail - swapfree + 512) / 1024; fhs->swap_stat[2] = ( swapfree + 512 ) / 1024; } else { fhs->swap_stat[0] = ( swapavail + 512 ) / 1024; fhs->swap_stat[1] = ( swapavail - swapfree + 512 ) / 1024; fhs->swap_stat[2] = ( swapfree + 512 ) / 1024; } swap_delay = 1; return true; } bool get_hostname( struct fhs_info * fi ) { if( gethostname( fi->hostname, HOST_NAME_MAX ) == 0 ) return true; else { printf("hostname get failed. [%d][%s]", errno, strerror(errno)); return false; } } #include #include #include int if_count[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT }; int if_info[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, 0, IFDATA_GENERAL }; bool get_network( struct fhs_info * fhs ) { // 기존 추출된 정보를 old 로 이동 처리후 0 reset memcpy( &(fhs->network_old), &(fhs->network_now), sizeof( struct network_info)); memset( &(fhs->network_now), 0x00, sizeof(struct network_info)); u_int count = 0; size_t data_len = sizeof(count); if( sysctl( if_count, 5, (void *)&count, (size_t *)&data_len, (void *)NULL, (size_t)0 ) != 0 ) { printf("Network interface count get failed. [%d][%s]", errno, strerror(errno)); return false; } // interface 가 없는 경우 if( count <= 0 ) return true; int i; struct ifmibdata data; data_len = sizeof( struct ifmibdata ); struct network_info total; memset( &total, 0x00, sizeof(struct network_info)); for( i = 1; i <= count ; i++ ) { if_info[4] = i; if( (sysctl( if_info, 6, (void *)&data, (size_t *)&data_len, (void *)NULL, (size_t)0 ) != 0) && (errno != ENOENT) ) { printf("Network interface sysctl error getting interface data. [%d][%s]", errno, strerror(errno)); return false; } // local loopback interface (lo) 제외 // - 장비의 트래픽 정보를 수집하는 것이므로.. lo 꺼는 빼는 것이 맞다. if( strncmp( data.ifmd_name, "lo", 2) == 0 ) continue; // link aggregation 처리되 lagg 쨒nterface 제외 // - link ggreagtion 처리된 개별 interface 통계가 lagg 에 sum 되어 나타나므로... 통계 중복 발생. // - 이를 해결하기 위해 lagg interface 는 수집 제외 if( strncmp( data.ifmd_name, "lagg", 4) == 0 ) continue; //printf("Network interface name : %s\n", data.ifmd_name ); total.inbound_packets += data.ifmd_data.ifi_ipackets; total.outbound_packets += data.ifmd_data.ifi_opackets; total.inbound_bytes += data.ifmd_data.ifi_ibytes; total.outbound_bytes += data.ifmd_data.ifi_obytes; } // 시간 정보 추출 clock_gettime( CLOCK_MONOTONIC, &(total.check_time)); memcpy( &(fhs->network_now), &total, sizeof( struct network_info)); return true; } #include #include void print_mountinfo() { int mntsize; struct statfs *mntbuf; long blocksize; int i; getbsize( &mntsize, &blocksize); //printf("\nblocksize = %ld\n", blocksize); mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); printf("\nMount: /stg\n"); printf(" Filesystem Type Size(M) Used(M) Avail(M) Capacity Mounted on\n"); for( i = 0; i < mntsize; i++ ) { if( strncmp( "/stg", mntbuf[i].f_mntonname, 4) == 0 ) { int64_t used = mntbuf[i].f_blocks - mntbuf[i].f_bfree; int64_t availblks = mntbuf[i].f_bavail + used; printf(" %-12s", mntbuf[i].f_mntfromname ); printf(" %-7s" , mntbuf[i].f_fstypename ); printf(" %10jd" , mntbuf[i].f_blocks * mntbuf[i].f_bsize / 1024 / 1024 ); printf(" %11jd" , (( used * mntbuf[i].f_bsize + 1023) / 1024 + 1023 ) / 1024 ); printf(" %11jd" , mntbuf[i].f_bavail * mntbuf[i].f_bsize / 1024 / 1024 ); printf(" %8.0f%%" , availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); printf(" %s" , mntbuf[i].f_mntonname); printf("\n"); } } return; } #include #include struct gmesh gmp; void *sp, *sq; double dt; struct timespec tp, tq; struct devstat *gsp, *gsq; void print_diskstat() { int i; uint64_t queuelength; long double busy; struct gident *gid; struct gprovider *pp; struct gconsumer *cp; sp = geom_stats_snapshot_get(); if (sp == NULL) err(1, "geom_stats_snapshot()"); geom_stats_snapshot_timestamp(sp, &tp); dt = tp.tv_sec - tq.tv_sec; dt += (tp.tv_nsec - tq.tv_nsec) * 1e-9; tq = tp; geom_stats_snapshot_reset(sp); geom_stats_snapshot_reset(sq); printf("Disk stat:\n"); printf(" Queue_length Busy(%%) Name\n"); for(;;) { gsp = geom_stats_snapshot_next(sp); gsq = geom_stats_snapshot_next(sq); if (gsp == NULL || gsq == NULL) break; if (gsp->id == NULL) continue; gid = geom_lookupid(&gmp, gsp->id); if (gid == NULL) { geom_deletetree(&gmp); i = geom_gettree(&gmp); if (i != 0) err(1, "geom_gettree = %d", i); gid = geom_lookupid(&gmp, gsp->id); } if (gid == NULL || gid->lg_what == ISCONSUMER ) continue; if ( gid->lg_what == ISPROVIDER && ((struct gprovider *)(gid->lg_ptr))->lg_geom->lg_rank != 1) continue; if (gsp->sequence0 != gsp->sequence1) { printf("*\n"); continue; } devstat_compute_statistics(gsp, gsq, dt, DSM_QUEUE_LENGTH, &queuelength, DSM_BUSY_PCT, &busy, DSM_NONE); printf(" "); printf("%12ju", (uintmax_t)queuelength ); printf(" %6.1lf ", (double)busy ); if (gid == NULL) { printf("??"); } else if (gid->lg_what == ISPROVIDER) { pp = gid->lg_ptr; printf("%s", pp->lg_name); } else if (gid->lg_what == ISCONSUMER) { cp = gid->lg_ptr; printf("[CONSUMER] %s/%s/%s", cp->lg_geom->lg_class->lg_name, cp->lg_geom->lg_name, cp->lg_provider->lg_name); } printf("\n"); *gsq = *gsp; } geom_stats_snapshot_free(sp); return; } #include #include #include #include #include #include #include #include #define TCPSTATES #include #define C(x) ((u_int)((x) & 0xff)) void print_session() { int total = 0 ; int total_80 = 0; int total_80_establish = 0; const char * mibvar = "net.inet.tcp.pcblist"; size_t len = 0; char * buf = NULL; printf("TCP Session stat:\n"); if( sysctlbyname( mibvar, 0, &len, 0, 0 ) < 0 ) { if(errno != ENOENT) fprintf(stderr, " - sysctlbyname(%s...) get length failed: %s\n", mibvar, strerror(errno)); else fprintf(stderr, " - sysctlbyname(%s...) not found. OS version check[%s]\n", mibvar, strerror(errno)); return; } buf = malloc(len); if( buf == NULL ) { fprintf(stderr, " - malloc error :%lu byte [%s]\n", (u_long)len, strerror(errno)); return; } if( sysctlbyname( mibvar, buf, &len, 0, 0 ) < 0 ) { fprintf(stderr, " - sysctlbyname(%s...) get data failed: %s\n", mibvar, strerror(errno)); free(buf); return; } /* struct xinpgen *xig, *oxig; struct xsocket *so; struct xtcp_timer *timer; struct tcpcb *tp = NULL; struct inpcb *inp; const char * vchar; char line[80]; int port; oxig = xig = (struct xinpgen *)buf; printf(" %-5.5s %-6.6s %-6.6s %-22.22s %-22.22s (state)\n", "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address"); for (xig = (struct xinpgen *)((char *)xig + xig->xig_len) ; xig->xig_len > sizeof(struct xinpgen) ; xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { timer = &((struct xtcpcb *)xig)->xt_timer; tp = &((struct xtcpcb *)xig)->xt_tp; inp = &((struct xtcpcb *)xig)->xt_inp; so = &((struct xtcpcb *)xig)->xt_socket; // Ignore sockets for protocols other than the desired one. if (so->xso_protocol != IPPROTO_TCP) continue; // Ignore PCBs which were freed during copyout. if (inp->inp_gencnt > oxig->xig_gen) continue; if ((inp->inp_vflag & INP_IPV4) == 0) continue; vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : " "; if ((tp->t_flags & TF_TOE) != 0) printf(" %-3.3s%-2.2s ", "toe", vchar); else printf(" %-3.3s%-2.2s ", "tcp", vchar); printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc); if (inp->inp_vflag & INP_IPV4) { //inetprint(&inp->inp_laddr, (int)inp->inp_lport, "tcp", 1); inp->inp_laddr.s_addr = ntohl(inp->inp_laddr.s_addr); port = ntohs((u_short)inp->inp_lport); if( inp->inp_laddr.s_addr == INADDR_ANY) { sprintf( line, "*"); } else { sprintf( line, "%u.%u.%u.%u" , C(inp->inp_laddr.s_addr >> 24) , C(inp->inp_laddr.s_addr >> 16) , C(inp->inp_laddr.s_addr >> 8) , C(inp->inp_laddr.s_addr)); } if(port == 0 ) { strcat( line, ".* "); } else { char temp[80]; sprintf( temp, ".%d ", port); strcat( line, temp); if( port == 80 ) { total_80++; if( tp && tp->t_state == 4 ) total_80_establish++; } } printf("%-22.22s ", line); //inetprint(&inp->inp_faddr, (int)inp->inp_fport, name, 1); inp->inp_faddr.s_addr = ntohl(inp->inp_faddr.s_addr); port = ntohs((u_short)inp->inp_fport); if( inp->inp_faddr.s_addr == INADDR_ANY) { sprintf( line, "*"); } else { sprintf(line, "%u.%u.%u.%u" , C(inp->inp_faddr.s_addr >> 24) , C(inp->inp_faddr.s_addr >> 16) , C(inp->inp_faddr.s_addr >> 8) , C(inp->inp_faddr.s_addr)); } if(port == 0 ) { strcat( line, ".* "); } else { char temp[80]; sprintf( temp, ".%d ", port); strcat( line, temp); } printf("%-22.22s ", line); } //printf(" %d", tp->t_state); if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) printf("%d", tp->t_state); else printf("%s", tcpstates[tp->t_state]); printf("\n"); total++; } */ struct xinpgen *xig, *oxig; struct xsocket *so; struct inpcb *inp; struct tcpcb *tp = NULL; int port; oxig = xig = (struct xinpgen *)buf; for (xig = (struct xinpgen *)((char *)xig + xig->xig_len) ; xig->xig_len > sizeof(struct xinpgen) ; xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { so = &((struct xtcpcb *)xig)->xt_socket; inp = &((struct xtcpcb *)xig)->xt_inp; tp = &((struct xtcpcb *)xig)->xt_tp; // Ignore sockets for protocols other than the desired one. if( so->xso_protocol != IPPROTO_TCP ) continue; // Ignore PCBs which were freed during copyout. if( inp->inp_gencnt > oxig->xig_gen ) continue; // IP v4, v6 가 아닌 경우 제외 if( (inp->inp_vflag & INP_IPV4) == 0 && (inp->inp_vflag & INP_IPV6) == 0 ) continue; total++; // Local port 정보 주출. port = ntohs((u_short)inp->inp_lport); if( port == 80 ) { total_80++; if( tp && tp->t_state == 4 ) total_80_establish++; } } free(buf); printf(" TCP session : %5d\n", total ); printf(" TCP 80 port session : %5d\n", total_80 ); printf(" TCP 80 port establish session: %5d\n", total_80_establish ); return; } void print_fhsinfo( struct fhs_info * fhs ) { // Hostname printf("\nHostname : %s", fhs->hostname ); // Load average /* printf("\nLoad averages"); for (i = 0; i < 3; i++) { printf("%c %5.2f", i == 0 ? ':' : ',', fhs->load_avg[i] ); } */ // 5분 정보만 사용 printf("\nLoad average (5min) : %5.2f", fhs->load_avg[1]); // CPU // - 변동률이 커서 사용하지 않는다. /* char *cpustatenames[CPUSTATES] = { "user,", "nice,", "system,", "interrupt,", "idle" }; printf("\nCPU: "); for( i=0; i < CPUSTATES; i++) { printf( "%4.1f%% %s", fhs->cpu_stat[i], cpustatenames[i]); } */ // Memory // - 사용률 정보만 사용 ( total - free )/total * 100 /* char *memorynames[] = { "M Active, ", "M Inact, ", "M Wired, ", "M Cache, ", "M Buf, ", "M Free" }; printf("\nMem: "); for( i=0; i < 6; i++ ) { printf("%d%s", fhs->memory_stat[i], memorynames[i]); } */ printf("\nMemory usage (%%) : %3.0f%%\n - total: %8dM\n - free : %8dM" , (fhs->memory_total - fhs->memory_stat[5]) * 100.0 / fhs->memory_total , fhs->memory_total , fhs->memory_stat[5] ); // Swap // - 사용률 정보만 사용 /* char *swapnames[] = { "M Total, ", "M Used, ", "M Free, ", "% Inuse, ", "K In, ", "K Out" }; printf("\nSwap: "); for( i=0; i < 6; i++ ) { printf("%d%s", fhs->swap_stat[i], swapnames[i]); } */ printf("\nSwap usage (%%) : %d%%\n - total: %8dM\n - used : %8dM" , fhs->swap_stat[3] , fhs->swap_stat[0] , fhs->swap_stat[1] ); // Mount info print_mountinfo(); // Disk stat print_diskstat(); // Network info printf("Network stat:\n"); if( fhs->network_now.check_time.tv_sec == 0 && fhs->network_now.check_time.tv_nsec == 0 ) { printf(" - not vaild"); } else { double elapsed = 0.0; elapsed = (fhs->network_now.check_time.tv_sec - fhs->network_old.check_time.tv_sec) + ((fhs->network_now.check_time.tv_nsec - fhs->network_old.check_time.tv_nsec) * 1e-9); printf(" check period : %12.1f sec\n", elapsed ); printf(" inbound packets : %12lu\n", fhs->network_now.inbound_packets - fhs->network_old.inbound_packets ); printf(" outbound packets: %12lu\n", fhs->network_now.outbound_packets - fhs->network_old.outbound_packets ); printf(" inbound traffic : %12.0f Byte/sec\n", (fhs->network_now.inbound_bytes - fhs->network_old.inbound_bytes) / elapsed ); printf(" outbound traffic: %12.0f Byte/sec\n", (fhs->network_now.outbound_bytes - fhs->network_old.outbound_bytes) / elapsed ); } // Session info print_session(); //printf("\n"); return; } /* Log base 2 of 1024 is 10 (2^10 == 1024) */ #define LOG1024 10 int main () { struct fhs_info fhs; // For Memory int pagesize = getpagesize(); pageshift = 0; while (pagesize > 1) { pageshift++; pagesize >>= 1; } /* we only need the amount of log(2)1024 for our conversion */ pageshift -= LOG1024; // For Swap kd = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, "kvm_open"); if (kd == NULL) return (-1); // Disk stat int i; int error; i = geom_gettree(&gmp); if (i != 0) err(1, "geom_gettree = %d", i); error = geom_stats_open(); if (error) err(1, "geom_stats_open()"); sq = NULL; sq = geom_stats_snapshot_get(); if (sq == NULL) err(1 , "geom_stats_snapshot()"); geom_stats_snapshot_timestamp(sq, &tq); // Print system info while(1) //for( int count = 0 ; count < 1000; count++ ) { get_loadavg ( &fhs ); get_cpuusage( &fhs ); get_memory ( &fhs ); get_swap ( &fhs ); get_hostname( &fhs ); get_network ( &fhs ); print_fhsinfo( &fhs ); //printf("\n%-*s %s", 20, "FileSystem", "aaa"); sleep(1); } kvm_close( kd ); return 0; }