tomcat에 일부 로그들이 계속 쌓이게 되어 일정 주기를 설정하여 자동으로 삭제하도록 하는 프로세스를 개발하였다.

catalina.out 로그는 리눅스에서 logrotate.d에 등록하여 쉽게 관리할 수 있으나, localhost.*.log, localhost_access_log.*.txt, manager ... , 특정 was 로그 등 log4j나 logback에서 maxhistory로 최대 파일갯수를 설정하였는데 삭제가 안되는 이슈가 있었기 때문에 이러한 프로세스를 개발하게 되었다.

 

1. 패키지 구성

패키지는 main 메소드가 있는 LogRotate.java 와 FilenameFilter interface를 상속받는 MyFilenameFilter.java로 구성하였다.

 

먼저 MyFilenameFilter.java의 소스를 확인하자.

<MyFilenameFilter.java 소스>

package com.logrotate;

import java.io.File;
import java.io.FilenameFilter;

public class MyFilenameFilter implements FilenameFilter{

	private String file_name;
	
	public MyFilenameFilter(String file_name) {
		this.file_name=file_name;
	}
	
	@Override
	public boolean accept(File dir, String name) {
		// TODO Auto-generated method stub
		if(name.contains("ucex")) {
			return name.split("_")[0].equals(file_name);
		}else {
			return name.split("\\.")[0].equals(file_name) && !name.contains("out");
		}
	}

}

FilenameFilter interface를 상속받은 class에서 마지막 남은 로그의 갯수를 확인하기 위해 override한 accept 메소드를 위와 같이 구현하였다.

ucex는 특정 was 프로젝트의 이름으로 해당 프로젝트에서 ucex_2019-xx-xx_x.log 형태로 로그를 생성하여 split("_")을 통해 ucex가 포함된 로그가 filter되도록 정의하였다.

else문에서는 localhost.2019-xx-xx.log, localhost_access_log.2019-xx-xx.txt, 등 해당 로그들에 대한 filter를 정의해 주었으며, out이 포함된 로그는 제외하도록 하였다.(catalina.out로그는 리눅스의 logrotate.d에서 관리)

<LogRotate.java 소스>

package com.logrotate;

import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Date;

public class LogRotate{
	
	public String[] filenameFilter(File file) {

		String file_name="";
		if(file.getName().contains("ucex")) {
			file_name=file.getName().split("_")[0];
		}else {
			file_name=file.getName().split("\\.")[0];
		}
		
		return new File(file.getParent()).list(new MyFilenameFilter(file_name));
	}
	
	//first arg : 파일 경로, second arg : 삭제 기준일
	public static void main(String [] args) {
		LogRotate dt = new LogRotate();
		long todayMil = new Date().getTime();
		//1일을  milliseconds로 환산
		long oneDayMil = 24*60*60*1000;
		File path = null;
		int delete_standard_day = Integer.parseInt(args[args.length-1]);
		System.out.println("File Delete Standard Day : "+delete_standard_day);
		for(int j=0;j<args.length-1;j++) {
			String file_path = args[j];
			
			System.out.println("File Delete Dir Path : "+file_path);
			
			path = new File(file_path);
			//catalina.out 로그는 제외
			File[] file_list = path.listFiles(new FilenameFilter() {
				
				@Override
				public boolean accept(File dir, String name) {
					// TODO Auto-generated method stub
					return !name.contains("out");
				}
			});
			Arrays.sort(file_list);
			for(int i=0;i<file_list.length;i++) {
				//파일의 마지막 수정 시간 가져오기
				long fileDayMil = todayMil - file_list[i].lastModified();
				int fileDay = (int)(fileDayMil/oneDayMil);
				int len = dt.filenameFilter(file_list[i]).length;
				if(len>1 && fileDay>delete_standard_day) {
					file_list[i].delete();
					System.out.println("Delete to File Name : "+file_list[i].getName());
				}					
			}
		}	
		System.exit(0);
	}
}

LogRotate.java에서는 main()과 filenameFilter()를 정의하였다.

main()는 파일경로와 삭제 기준일을 arguments값으로 받으며, 마지막 arguments값은 무조건 삭제 기준일이여야 한다.

Date()를 이용하여 현재 시간값을 구하고 각 파일들의 시간값들과 비교하여 main()에 arguments값으로 넘어온 삭제 기준일과 비교하여 삭제하도록 구현하였다.

또한 filenameFilter()에서 해당 MyFilenameFilter생성자를 사용하여 각 파일에 대한 갯수를 가져올 수 있도록 하여 각 로그파일들이 1개씩 남아있을 경우 지우지 않도록 구현하였다.

파일 삭제가 종료될 시에 해당 프로세스를 자동으로 종료하도록 System.exit(0)를 넣어주었다.

(jar파일로 실행할 경우 종료해주지 않으면 프로세스가 계속 살아있어 추후에 크론이 주기적으로 실행시킬 경우 해당 프로세스가 계속 쌓이게됨)

 

<logrotate_start.sh 소스>

#!/bin/sh

logrotate_path=/home/cmuc/logrotation
tomcat_log_path=/home/cmuc/tomcat/apache-tomcat-7.0.47/logs
ucex_log_path=/home/cmuc/ucex/logs
logrotate_log_path=/home/cmuc/logrotation
delete_day=30

sleep 1

#LAST argumetns is delete_day
java -jar ${logrotate_path}/LogRotate.jar ${tomcat_log_path} ${ucex_log_path} ${delete_day} > ${logrotate_log_path}/logrotate.log

java소스들을 jar파일로 컴파일한 후 위의 쉘스크립트를 리눅스의 crontab에 등록하여 매일 새벽 3시에 동작하도록 하였다.

<crontab 등록 예시> 0 3 * * * cmuc /home/cmuc/logrotation/logrotate_start.sh

모든 경로는 절대 경로로 지정해야 crontab에서 정상적으로 동작한다. 위의 경로들은 프로젝트에 맞게 변경해주면 되겠다.

 

ps. 티스토리 패치 후에 소스코드 안에 <code></code>값이 계속 들어가 사라지지 않네요..

'java' 카테고리의 다른 글

OutOfMemory(OOME) 분석 및 java tomcat 튜닝  (0) 2019.04.05

+ Recent posts