warn함수 출력을 로그파일로 기록하기

전종필

프로그램이 어떤 오류를 감지하게되면 die나 warn함수를 사용해서 오류내용을 출력해 주는것이 좋은 습관입니다. 예를 들어

my $member_count = @members; # 멤버의 숫자를 센다.
my $valeach = $total / $member_count;
print "각자 $valeach 씩을 차지함\n";
그러나, 위 프로그램에는 오류가 발생할 가능성이 있습니다. 만일 @members 배열에 요소가 하나도 없다면 $member_count는 0이 되므로

Illegal division by zero at - line ....
과 같은 오류가 출력되며 프로그램이 강제종료됩니다.
따라서

my $member_count = @members; # 멤버의 숫자를 센다.
if( $member_count ) {
	my $valeach = $total / $member_count;
	print "각자 $valeach 씩을 차지함\n";
}
else {
	$save += $total;
	warn "멤버가 생길 때 까지 창고에 쌓아둡니다.\n";
}
와 같이 오류를 미리 검출하고 경고메시지를 출력하는 것이 좋겠지요.

그러나, 어떤 프로그램들은 데몬(저 혼자 돌아가는...)으로 만들어지기도 하고, 혹은 crontab의 스케쥴로 걸어두기도 하기 때문에 오류가 있을 경우 warn함수가 출력하는 내용은 무시되어질 수 있습니다.
이 경우 같은 내용을 특정파일(로그파일)에 적어두면, 나중에 어떤 문제가 있었는지 확인할 수 있게됩니다.
그러므로,

....
	log_to_my_log_file( "멤버가 생길 때 까지 창고에 쌓아둡니다.\n" ); # 함수를 만들어서...
...
와 같이 한다면 되겠죠.
그러나, 이 프로그램이 만든지 오래되었고, warn 내장함수를 새로운 사용자정의함수로 일일이 바꿔주기도 귀찮은 일이 될 수 있습니다.
이럴 ��에는 $SIG{__WARN__} 시그널 핸들러를 사용하여 처리해 주면 됩니다.

프로그램의 어딘가에

BEGIN {
	$SIG{'__WARN__'} = sub {
		my($sec,$min,$hour,$mday,$mon,$year,$wday) = localtime();
		my $logfile = "/mydir/log/my.$wday.log";
		if( (-M $logfile) > 3 ) {
			# 하루에 한개의 파일이므로 오래된것은 지워버린다. 싫음 말고...
			unlink($logfile);
		}

		if(open(LOG,">>$logfile")) {
			# 날짜, process id와 함께 기록한다.
			print LOG "$$ : ", scalar(localtime()), " ", @_;
			close LOG;
		}
		warn @_; # 필요없다면 빼줍니다.
		# 재귀적으로 핸들러를 호출하지 않으므로 걱정마세요.
	};
}
를 넣어줍니다.
파일이름이나 저장할 내용들은 마음대로 조정하면 됩니다. 꼭 기억할 것은 $SIG{'__WARN__'} = sub {....}; 구문으로, 프로그램의 시작시에 선언되도록 BEGIN 함수에 넣어주도록 합니다. 이렇게 하면 warn함수가 호출될 때마다 warn함수에 전달되었던 내용이 $SIG{'__WARN__'}에 지정된 핸들러로 전달되어 위와같이 처리할 수 있게 됩니다.
어떻습니까? Perl적이죠? 
Comments