IT_Server/Linux

[펌] Crontab 으로 java의 jar 스케줄러 만들기

JJun ™ 2013. 1. 17. 14:47



 출처: http://savinglove.tistory.com/13



자바 클래스파일을 java path 맞춰가면서 cron 에 등록 하려고 하는 분들도 있지만
간단하게 클래스 파일들을 jar 파일로 만들어서 cron 에 스케줄 등록 하면 
여러가지 신경 쓸 필요도 없고 좋습니다.



[crontab 명령]

* 등록된 crontab 스케줄 보기, 수정, 삭제 명령
보기> crontab  -l
수정> crontab  -e
삭제> crontab  -r


*jar 파일에 실행 권한 설정
> chmod  755  파일명.jar

* jar 파일 실행 명령
> java  -jar  파일명.jar  [args]
또는
> $JDK_HOME/bin/java  -classpath  파일명.jar  클래스명  [args]

[args] => "arg1"  "arg2"  "arg3" ... 형태로 넣으면 됩니다.

* 매일 새벽 1시에 jar 파일 실행 하도록 스케줄 걸기
0 1 * * * * java -jar 파일명.jar [args]

추가설명) 순서대로
첫번째 : 분
두번째 : 시간
세번째 : 일
네번째 : 월
다섯번째 : 요일 [0~6 이며 0은 일요일을 의미]

* 시간 동기화 (매월 1일 새벽 1시)
0 1 1 * * * /usr/bin/rdate -s time.bora.net

* 서버 재시작 (매월 1일 새벽 2시)
0 2 1 * * * /usr/bin/reboot

* cron 데몬 재시작 명령
> service crond restart

* cron 동작 로그 확인
> cat  /var/log/cron



이상으로 간단한 cron 스케줄 등록 사용법을 정리해 보았습니다.
cron 은 주기적으로 실행을 시키기 위해서 스케줄 등록 하는 명령어 입니다.
참고로 한번만 실행하고 종료 해야 하는 스케줄을 등록 하려면 at 명령어를 사용 합니다.





[crontab 사용법]


일정 주기로 처리하는 배치 프로세스의 경우 시스템 crontab에 등록 하여 자동화 시킬 수 있다.



* crontab 명령

 
   $ crontab [-e | -l | -r]

   -e: 등록된 crontab을 편집한다.

   -l: 등록된 crontab명령을 출력한다.

   -r: 등록된 crontab을 삭제한다.

 



* crontab 편집

 
   $ crontab -e


위 명령을 입력하면 vi 환경에서 crontab 편집이 된다


 
 20 13 * * 7 /home/batch/script/backup.sh

 0 6 1 3 * /home/batch/script/logdel.sh

 0 0 * * * /home/batch/script/daybatch.sh

 30 * * * * /home/batch/script/hourbatch.sh

 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /home/batch/script/checksys.sh

 


위 내용은 vi 환경에서 crontab 샘플이다.

구분자는 공백으로 앞에서 부터 분(0~59), 시(0~23), 일(1~31), 월(1~12), 주(1:월~7:일),  실행명령을 의미한다.  ","(컴마)를 구분자로 복수 시간을 지정할 수 있다.


backup.sh는 매주 일요일 13:20에 기상시간을 알리며 실행된다.

logdel.sh는 매년 3월 1일 06:00에 삼일절을 기념으로 실행된다.

daybatch.sh는 매일 00시 00분에 퇴근시간을 알리며 실행된다.

hourbatch.sh는 매시간 30분에 실행된다. 

checksys.sh는 5분마다 실행된다.



* crontab 사용시 주의 사항


crontab 으로 명령이 수행되면 기존 환경변수를 인식 하지 못한다.


crontab에 아래의 프로세스가 등록되어 있다고 가정하자.

 
   0 * * * * /home/batch/bin/run_hourbatch


run_hourbatch는 오라클을 연동하는 Pro-C로 만들어져 있다고 가정하자.

이 프로세스는 1시간 간격으로 수행되는 배치 프로세스이다.


하지만, 이렇게 프로세스를 직접 실행을 하면 수행에 실패한다.


 Error while trying to retrieve text for error ORA-12154


로그를 확인해 보면 위와 같은 메시지와 함께 DB 커넥션을 하지 못한다.


이는 crontab에 등록된 프로세스가 실행되면서 .profile에 등록된 오라클 환경변수를 

읽어 들이지 않기 때문에 발생하는 것이다. 


crontab의 내용을 아래와 같이 수정하자

 
 30 * * * * /home/batch/script/hourbatch.sh


그리고 아래와 같은 hourbatch.sh라는 shell script를 생성한다.


 
 $ vi /home/batch/script/hourbatch.sh

 #!/bin/ksh

 # 오라클 환경 변수 설정

 ORACLE_SID=TESTDB;

 export ORACLE_SID

 ORACLE_BASE=/home/oracle/app/oracle;

 export ORACLE_BASE

 ORACLE_HOME=$ORACLE_BASE/product/9.1.1;

 export ORACLE_HOME

 ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data;

 export ORA_NLS33

 ORACLE_TERM=vt100;

 export ORACLE_TERM

 NLS_LANG=American_America.KO16KSC5601;

 export NLS_LANG

 PATH=$ORACLE_HOME/bin:$PATH;

 export PATH

 TNS_ADMIN=$ORACLE_HOME/network/admin;

 export TNS_ADMIN


 # batch 기동 로그 파일

 BATCHLOG=`date '+%y%m%d_batch.log'`


 # 시간 배치 실행

 echo `date '+%H:%M'` + "^Hour Batch START" >> "/home/batch/log/"$BATCHLOG

 /home/batch/bin/run_hourbatch

 echo `date '+%H:%M'` + "^Hour Batch END" >> "/home/batch/log/"$BATCHLOG

 


이렇게 하고 hourbatch.sh에 실행 권한을 주면 

매시간 30분이 되면 run_hourbatch가 정상적으로 실행된다.








crontab 은 유저의 환경 변수를 가져오지 않는다.


문제:

이번에 서버 변경 작업을 하면서 기존 서버에 crontab 으로 등록되어 있는 내용을 똑같이 옮겨왔다.

정해진 시간에 몇 개의 쉘 프로그램을 실행시키는 구문이었는데,

이 놈들이 정상적으로 실행되지 않는다.


확인해보니, 각 쉘 프로그램에서는 자바의 루트 디렉토리를 칭하는 JAVA_HOME 환경 변수를 사용하는데,

이번 서버 변경 작업때문에 자바의 디렉토리 위치가 변경되었기 때문이었다.


어쩔 수 없이 각 파일을 열어 JAVA_HOME 변수를 설정하다가 문득,

'환경 변수를 왜 모든 쉘 프로그램에 각각 등록해둔 거지..?' 라고 생각하면서

JAVA_HOME 변수를 .profile 에 환경 변수로 추가하고 쉘 프로그램에 등록되어 있던 JAVA_HOME 은 삭제했다.


테스트로 sh 파일을 수행해보니, 잘 돌아간다~


그런데~~ 다음 날, crontab 에서 에러가 났다~~~~

sh 파일만 따로 수행하면 문제없이 잘 되는데, 왜 이런 걸까...

혹시 crontab 에서는 유저의 환경 변수를 가져오지 못하는가...?


해결책:

crontab 은 환경 변수를 가지지 않은 체로 실행된다고 한다.

그래서 환경 변수를 사용할 경우, 각 쉘 프로그램에서 따로 설정해주어야 한다.

(기존에 모든 쉘 프로그램에 같은 내용의 환경 변수가 각각 설정되어 있던 이유가 이거였다...)


자세한 내용은 아래 포스트를 참고하자.

http://sooyasarang.tistory.com/tag/%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98

더보기


[cron이 환경변수를 상속하지 않는 이유]


이번에 cron에 어떤 쉘 스크립트를 등록했는데 제 시간에 수행되지 않는 경험을 했습니다. 

그래서 우선 cron내지는 crontab으로 검색을 해보니 "crontab에 등록했는데 실행이 안돼요."라는 

글들이 많았고 답변을 보면 대부분 환경변수 때문이었습니다.


이런 경험을 한 사람이 많은 이유가 뭘까요? 아마도 exec family 함수들 중에서 

execle(), execve()를 제외한 다른 함수들은 current process의 환경변수들을 

child process에게 상속시키는데, 늘 사용하는 bash같은 쉘들도 그렇게 구현해 놓았기 때문에 

무의식 중에 상속된다고 여기고 있었던 탓같습니다.


그럼 crond는 왜 child process에게 환경변수를 상속하지 않는 것일까요? 

그 이유는 user 마다 자신만의 crontab을 등록할 수있기 때문입니다. 

아마 대부분의 시스템에 crond는 root로 실행되고 있을 것이고, 

다른 user의 crontab을 실행시켜줄 때 당연히 root의 환경변수를 상속해서는 안됩니다. 

반대로 쉘의 입장에서 생각해보면 su를 이용해서 다른 계정으로 전환하지 않는한 

자신의 환경변수를 상속하는게 당연합니다.


정리하면, cron처럼 uid가 다른 child process를 fork & exec할 때는 execle()를 이용해서 

명시적으로 환경변수를 상속하지 않는 것이 맞고, 다른 대부분의 경우에는 parent process의 

환경변수를 상속받는게 편합니다.


이상의 이유를 담고 있는 cron의 사용법에 대해서 얘기를 하자면, crontab에 등록된 쉘 스크립트 

또는 바이너리가 사용할 모든 환경변수들은 아래처럼 crontab 첫 머리에 등록해줘야 합니다. 

예를 들어 PATH에 추가되는 사항이 있다면 꼭 적어줘야 합니다.  


SHELL=/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin

MAILTO=root

HOME=/

# run-parts

01 * * * * root run-parts /etc/cron.hourly

02 4 * * * root run-parts /etc/cron.daily

22 4 * * 0 root run-parts /etc/cron.weekly

42 4 1 * * root run-parts /etc/cron.monthly

그렇게 내용을 수정한 이후에 "#crontab -u user /etc/crontab"과 같이 crontab을 다시 등록해야 합니다.


이게 싫으면 각 쉘 스크립트 내지는 바이너리에서 환경변수를 한번 더 신경쓰면서 짜야합니다. :( 

그래서 또 스치는 의문이 하나 있었는데, 혹시 cron이 똑똑하게 마치 쉘이 처음 실행되 듯이 

시스템 default profile과 user별 profile을 찾아서 export해주진 않을까? 궁금해서 찾아봤습니다.


그 결과 최대한 심플하게 오로지 crontab에 등록된 환경변수들만 export한다는 것입니다. 

다시 왜 그랬을까 생각해보면 쉘이야 자기가 필요로 하는 default 파일 명을 define하고 시작할 수 있지만,

cron이 입장에서는 어떤 쉘위에서 수행될 지도 모르는 판에 그 짓(?)을 할 수는 없겠구나 싶었습니다.



※ 참고로 cron의 총 코드의 양은 *.c *.h만 계산했을 때 예상보다 훨씬 긴 4400여 줄정도였습니다. 

   그리고 내용을 조금 둘러보고 개발한 Paul Vixie에게 작은 존경을 표하고 싶을 정도로 

   각종 시스템 프로그래밍의 진수가 많이 녹아 있어서 학생들이 보면 좋을 교재같은 코드였습다. 

   그리고 코드의 정리도 깔끔했고 주석도 잘 달려있었습니다. 

   관심과 시간이 있으면 한번 구경해보시길 바라면서 이만...



http://kldp.org/node/59859


'IT_Server > Linux' 카테고리의 다른 글

[펌] Vi editor 명령어 집합  (0) 2009.04.13
linux 콘솔 화면에서 깨진글자 제어 하기  (0) 2007.12.02
[vi 편집기 설정 파일] vimrc  (0) 2007.10.09
[LINUX] 리눅스 명령어  (0) 2007.07.05
[LINUX] 서버 Tip  (0) 2007.07.05