[완료] [질문] perl - vmstat 결과의 평균 (array의 칼럼별 평균)
안녕하세요.
vmstat 의 결과가 보통 아래와 같은 형식으로 나옵니다.
procs memory page faults cpu
r b avm free re pi po fr sr cy in sy cs us sy wa id
8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38
5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29
6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31
4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47
6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32
이 결과를 string으로 받아서
행렬 계산하듯이 하면 각 항목별 평균을 구할 수 있는데
혹시 보다 쉬운 방법으로 각 항목별 평균을 구하는 방법이 있으면 알려주세요.
$ret = `vmstat 1 6 | tail -5 ` ;
감사합니다.


일반적인 방법
일반적인 방법
#!/usr/bin/env perl use strict; use warnings; my @sum; my $row_cnt = 0; while (<DATA>) { my $col_cnt = 0; foreach my $num ( split /\s+/, $_ ) { $sum[$col_cnt] += $num; $col_cnt++; } $row_cnt++; } my @average = map { $_ / $row_cnt } @sum; print "@average\n"; __DATA__ 8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38 5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29 6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31 4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47 6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32결과
질문이 있습니다. my
먼저 답변에 감사드립니다.
질문이 있습니다.
my @average = map { $_ / $row_cnt } @sum;
구문에 대해서 설명을 부탁드려도 될까요?
그리고 vmstat 결과를 string 변수에 담아서 처리하므로
아래와 같이 구현했습니다.
# 평균을 구한다.
$row_cnt = 0 ;
# $ret = `vmstat 1 $vmstat_cnt | tail -($vmstat_cnt -1) ` ;
$ret = " 8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38
5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29
6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31
4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47
6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32" ;
@vm_sum = "" ;
@vmstats = "" ;
foreach $line ( split /\n/, $ret ) {
$line =~ s/^\s*//g ;
# chomp($line) ;
$col_cnt = 0;
foreach $value ( split /\s+/, $line ) {
# @vmstats = split / +/, $line ;
$vm_sum[$col_cnt] += $value ;
$col_cnt++;
}
$row_cnt++;
}
@vmstats = map { $_ / $row_cnt } @vm_sum ;
print "row_cnt : ", "$row_cnt\n";
print "col_cnt : ", "$col_cnt\n";
print "@vm_sum\n";
print "@vmstats\n";
my @average = map { $_ / $row_cnt } @sum; 는
my @average = map { $_ / $row_cnt } @sum; 에서
우선 map 함수의 용도는 http://perldoc.perl.org/functions/map.html 을 보시면 되며
map은 함수형언어의 특징을 가져온 것이죠.
map은 다음과 같은 두가지 형태로 쓸 수 있으며
1. map 표현식,리스트
my @a = map $_*2, (1,2,3,4);
#@a는 (2,4,6,8)
2. map 블럭 리스트 (,가 없음을 주의, 블럭안에는 구문(statement)가 올 수 있다.)
my @b = (2,4,6,8)
my @a = map { $_/2 } @b;
#@a는 (1,2,3,4)
뒤의 리스트에서 하나씩 가져와서 표현식 혹은 블럭의 결과를 적용한 결과를 다시 리스트로 리턴합니다.
perl의 grep함수도 map이랑 비슷한 성격의 함수죠.
my @average = map { $_ / $row_cnt } @sum;
를 foreach를 사용해서 바꿔보면
my @average foreach (@sum) { push @average, $_ / $row_cnt; }처럼 되겠죠.
친절한 설명 정말
친절한 설명 정말 감사드립니다.
최종적으로 아래와 같이 만들었습니다. (제 목적은 완료했습니다.)
혹시 시간이 되시면 보시고 추가적인 조언 부탁드립니다. ^^
#!/usr/bin/env perl #!/usr/bin/perl #!/opt/perl/bin/perl ################################################################################ # vmstat.pl # # Developed 05/01/2006 by KueTae Kim # <a href="mailto:ktkim87@empal.com" rel="nofollow">ktkim87@empal.com</a> <a href="mailto:kuetae.kim@gmail.com" rel="nofollow">kuetae.kim@gmail.com</a> # # * 목적 # - DB 모니터링시 시스템 리소스(특히 CPU, Memory)를 같이 모니터링함. # - 가끔 DB 내부 리소스 경합보다는 시스템 리소스 부족으로 성능저하/장애발생함. # - 툴에서 제공하는 5분 주기의 평균값으로는 분석이 어려운 경우 존재함. # # * 용도 # - DB 장애시점 시스템 리소스 점검 # - DB 진단시 시스템 CPU, 메모리 관련 사용 추이 그래프 (Excel 활용) # # * 사용방법 # $ vmstat.pl 5 1000000 # # HISTORY: # Date Developer Description # ---------- --------- --------------------------- # 2006.05.01 ktkim HP-UX # 2007.12.15 ktkim AIX 추가 # 2009.04.05 ktkim Sun OS 추가 # 2009.09.20 ktkim 평균값으로 대체 ################################################################################ use strict; use warnings; # use DBI; use IO::Handle; use Time::HiRes qw(gettimeofday usleep tv_interval); my $ret ; my @vmstat_sum ; my @vmstat_avg ; my $run_cnt = 0 ; my $max_cnt = 17280 ; my $sleep_time = 5 ; my $vmstat_cnt = $sleep_time ; my $row_cnt ; my $col_cnt ; my $osname ; my $hostname ; my $curr_date = "1" ; my $tmp_date = "0" ; my $curr_datetime ; my $fname ; my $line ; my $value ; my $header_print = "N" ; my $header_count = 20 ; my $vmheader_SunOS ; my $vmheader_HPUX ; my $vmheader_AIX ; $vmheader_SunOS = qq{ kthr memory(GB) page faults cpu DateTime r b w swap free re mf pi po fr de sr in sy cs us sy id } ; $vmheader_HPUX = qq{ procs memory(GB) page faults cpu DateTime r b w avm free re at pi po fr de sr in sy cs us sy id } ; $vmheader_AIX = qq{ kthr memory(GB) page faults cpu DateTime r b avm free re pi po fr sr cy in sy cs us sy wa id } ; ################################################################################ # Command Line Input ################################################################################ if ( $#ARGV == 0 ) { $sleep_time = $ARGV[0] ; } elsif ( $#ARGV == 1 ) { $sleep_time = $ARGV[0] ; $max_cnt = $ARGV[1] ; } else { print "Usage: $0 sleep count \n" ; } $vmstat_cnt = $sleep_time ; ################################################################################ # Main ################################################################################ $osname = `uname -s` ; chomp($osname) ; $hostname = `hostname` ; chomp($hostname) ; $curr_date = currdate() ; $fname = "vmstat_" . $hostname . "_" . $curr_date . ".log" ; open( FH, "+>>" . $fname ) || die "Can't open log file $fname." ; FH->autoflush(1); while ( $max_cnt > $run_cnt ) { #----------------------------------------------------------------------------- # $tmp_date = currdate() ; if ( $curr_date ne $tmp_date ) { close( FH ) ; $curr_date = $tmp_date ; $fname = "vmstat_" . $hostname . "_" . $curr_date . ".log" ; open( FH, "+>>" . $fname ) || die "Can't open log file $fname." ; FH->autoflush(1); print $fname , "\n" ; } $ret = `vmstat 1 $vmstat_cnt | tail -($vmstat_cnt -1) ` ; # 평균을 구한다. @vmstat_sum = () ; @vmstat_avg = () ; $row_cnt = 0 ; foreach $line ( split /\n/, $ret ) { $line =~ s/^\s*//g ; # chomp($line) ; $col_cnt = 0; foreach $value ( split /\s+/, $line ) { # @vmstat_avg = split / +/, $line ; $vmstat_sum[$col_cnt] += $value ; $col_cnt++; } $row_cnt++; } @vmstat_avg = map { $_ / $row_cnt } @vmstat_sum ; if ( ( $run_cnt % $header_count ) == 0 ) { $header_print = "Y" } else { $header_print = "N" } if ( $osname eq "SunOS" ) { printf(FH $vmheader_SunOS ) if $header_print eq "Y" ; printf(FH "%s%4d%4d%4d %4.0f%4.0f %6d%6d%6d%6d %4d%4d%4d %7d%7d%7d %4d%4d%4d\n", currdatetime(), $vmstat_avg[0], $vmstat_avg[1],$vmstat_avg[2], $vmstat_avg[3]/1024/1024,$vmstat_avg[4]/1024/1024, $vmstat_avg[5],$vmstat_avg[6],$vmstat_avg[7],$vmstat_avg[8],$vmstat_avg[9],$vmstat_avg[10],$vmstat_avg[11], $vmstat_avg[16],$vmstat_avg[17],$vmstat_avg[18], $vmstat_avg[19],$vmstat_avg[20],$vmstat_avg[21] ) ; } elsif ( $osname eq "HP-UX" ) { printf(FH $vmheader_HPUX ) if $header_print eq "Y" ; printf(FH "%s%4d%4d%4d %4.0f%4.0f %6d%6d%6d%6d %4d%4d%4d %7d%7d%7d %4d%4d%4d\n", currdatetime(), $vmstat_avg[0], $vmstat_avg[1],$vmstat_avg[2], $vmstat_avg[3]/1024/1024,$vmstat_avg[4]/1024/1024, $vmstat_avg[5],$vmstat_avg[6],$vmstat_avg[7],$vmstat_avg[8],$vmstat_avg[9],$vmstat_avg[10],$vmstat_avg[11], $vmstat_avg[12],$vmstat_avg[13],$vmstat_avg[14], $vmstat_avg[15],$vmstat_avg[16],$vmstat_avg[17] ) ; } elsif ( $osname eq "AIX" ) { printf(FH $vmheader_AIX ) if $header_print eq "Y" ; printf(FH "%s%4d%4d %4.0f%4.0f %6d%6d%6d%7d%7d%7d %7d%7d%7d %4d%4d%4d%4d\n", currdatetime(), $vmstat_avg[0], $vmstat_avg[1], $vmstat_avg[2*4.0/1024/1024.0],$vmstat_avg[3]*4.0/1024/1024.0, $vmstat_avg[4],$vmstat_avg[5],$vmstat_avg[6], $vmstat_avg[7],$vmstat_avg[8],$vmstat_avg[9], $vmstat_avg[10],$vmstat_avg[11],$vmstat_avg[12], $vmstat_avg[13],$vmstat_avg[14],$vmstat_avg[16],$vmstat_avg[15] ) ; } $run_cnt = $run_cnt + 1 ; sleep 1 ; } sub currdate { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime() ; return( sprintf("%04d%02d%02d", $year+1900,$mon+1,$mday ) ) ; } sub currdatetime { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime() ; return( sprintf("%04d-%02d-%02d:%02d:%02d:%02d", $year+1900,$mon+1,$mday, $hour,$min,$sec) ) ; }반칙인것같긴 한데...
$ cat data.txt r b avm free re pi po fr sr cy in sy cs us sy wa id 8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38 5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29 6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31 4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47 6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32 $ R > colMeans(read.table("data.txt", header=T)) r b avm free re pi po fr 5.8 0.0 26.0 12.0 0.0 0.0 0.0 0.0 sr cy in. sy cs us sy.1 wa 0.0 0.0 12615.2 197855.4 47739.6 33.4 7.2 24.0 id 35.4 > q() Save workspace image? [y/n/c]: n $죄송...
댓글 달기