예약 작업과 cron
cron 시간 다섯 칸과 기호, 수동 검증 뒤 등록, cron의 빈 환경과 % 이스케이프, DBA 점검 스크립트 자동화와 8단계 문제 점검
#핵심 요약
cron은 정해진 시각에 명령이나 스크립트를 실행하는 스케줄러이며, 백그라운드의 crond가 1분마다 작업표(crontab)를 확인함
등록 순서는 스크립트 작성 → 실행 권한 → 손으로 먼저 실행 → crontab -e 등록 → 로그로 자동 실행 확인임
cron은 .bash_profile을 읽지 않아 ORACLE_HOME, ORACLE_SID, PATH가 비어 있으므로 스크립트 안에 직접 설정함
crontab 줄 안의 %는 특수 문자라 \%로 써야 하고, 스크립트 파일 안의 %는 그대로 씀
#개념과 동작 원리
시간 필드는 분(059), 시(023), 일(131), 월(112), 요일(0~7, 0과 7이 일요일)의 다섯 칸이고 그 뒤에 실행할 명령을 적음
| 시간 표현 | 실행 시각 |
|---|---|
* * * * * |
매분 |
0 2 * * * |
매일 02:00 |
30 6 * * * |
매일 06:30 |
0 0 * * * |
매일 자정 |
30 1 * * 0 |
일요일 01:30 |
0 23 * * 0 |
일요일 23:00 |
0 */6 * * * |
00, 06, 12, 18시 정각 |
*/10 * * * * |
10분 간격 |
0 9 1 * * |
매월 1일 09:00 |
0 0 * * 1-5 |
월~금 자정 |
*/30 9-18 * * 1-5 |
평일 9시~18시 사이 30분마다 |
| 기호 | 의미 |
|---|---|
* |
모든 값 |
*/n |
n 간격(시 필드의 */6은 0, 6, 12, 18) |
a-b |
범위 |
a,b |
지정한 값들만 |
60 2 * * *는 분이 059를 넘고, 23을 넘어 잘못된 표현임0 25 * * *는 시가 0
#필수 명령어 또는 SQL
#첫 작업 등록과 확인
#!/bin/bash
echo "$(date +"%Y-%m-%d %H:%M:%S") tick 실행됨" >> /home/oracle/cron_lab/logs/tick.logmkdir -p /home/oracle/cron_lab/logs
chmod +x tick.sh
./tick.sh
cat logs/tick.log
crontab -e
crontab -l
tail -f logs/tick.log* * * * * /home/oracle/cron_lab/tick.sh결과 해석:
손으로 먼저 실행해 로그에 한 줄이 찍히는지 확인한 뒤 등록함
건너뛰면 스크립트의 오타(date를 daet로 적는 등)를 다음 예약 시각에 로그가 비어 있는 것을 보고서야 알게 됨
등록 뒤 1분 간격으로 새 줄이 쌓이면 crond가 시간표를 읽어 실행한 것이며, tail -f는 Ctrl+C로 끝냄
요일과 날짜 필드는 date '+분=%M 시=%H 일=%d 월=%m 요일=%w'로 현재 값을 출력해 확인함
스크립트와 로그는 절대 경로로 적음
cron은 홈 디렉터리에서 실행되지만 상대 경로는 실행 위치에 따라 달라짐
#cron의 빈 환경 재현과 해결
#!/bin/bash
export ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1
export ORACLE_SID=<SID>
export PATH=$ORACLE_HOME/bin:$PATH
LOG=/home/oracle/cron_lab/logs/dba_$(date +"%Y%m%d").log
echo "===== $(date +"%Y-%m-%d %H:%M:%S") 점검 시작 =====" >> $LOG
sqlplus -s / as sysdba <<EOF >> $LOG 2>&1
select instance_name, status from v\$instance;
select count(*) invalid_objects from dba_objects where status='INVALID';
exit
EOF
echo "===== $(date +"%Y-%m-%d %H:%M:%S") 점검 종료 =====" >> $LOG* * * * * env >> /home/oracle/cron_lab/logs/cron_env.log결과 해석:
위 export 세 줄이 없을 때는 손으로 실행하면 되지만 cron에서는 sqlplus: command not found가 남음
같은 이유로 RMAN 백업 스크립트는 rman: command not found로 실패함
env를 cron으로 찍어 보면 ORACLE_HOME, ORACLE_SID가 없고 PATH도 /usr/bin:/bin 정도의 최소 경로뿐임
히어도큐먼트를 따옴표 없이(<<EOF) 쓰면 셸이 $를 풀므로 v\$instance처럼 이스케이프함
실습 기록: 환경변수를 넣은 뒤 cron 로그에 INSTANCE_NAME, STATUS가 정상 출력됨
#출력과 오류를 로그로, % 이스케이프
* * * * * /home/oracle/cron_lab/log_test.sh >> /home/oracle/cron_lab/logs/log_test.log 2>&1
* * * * * /bin/date +\%Y\%m\%d >> /home/oracle/cron_lab/logs/date_ok.log 2>&1
0 2 * * * /home/oracle/cron_lab/daily_backup.sh >> /home/oracle/cron_lab/logs/backup_$(date +\%Y\%m\%d).log 2>&1결과 해석:
2>&1을 빼면 오류 메시지는 로그에 남지 않아 장애 원인을 찾을 수 없음
crontab 줄에서 %는 줄바꿈으로 바뀌고 그 뒤는 명령의 표준입력으로 넘어감/bin/date +%Y%m%d로 등록하면 로그가 비거나 날짜가 찍히지 않고, \%로 쓰면 20260728처럼 정상 출력됨
날짜별 로그 파일 이름도 crontab 줄에서 만들면 같은 이유로 \%가 필요함
수업 자료의 확인 문제 답은 /%Y/%m/%d로 적혀 있으나 이스케이프 문자는 역슬래시(\%)임
스크립트 파일 안의 date +"%Y%m%d"는 crontab이 해석하지 않으므로 이스케이프하지 않음
날짜 처리를 스크립트 안으로 옮기면 crontab 줄이 단순해짐
#실행 기록 확인과 정리
systemctl status crond
journalctl -u crond --since "today" | grep oraclecrontab -l > ~/crontab_$(date +%Y%m%d).bak
crontab -e결과 해석:
스크립트 로그는 "무엇을 했는지", journalctl -u crond는 "언제 실행됐는지"를 보여 줌
수업 실습은 매번 crontab -r로 정리하는데, -r은 묻지 않고 그 계정의 작업표 전체를 지움
운영 계정에서는 crontab -l로 백업한 뒤 crontab -e에서 실습 줄만 지움
매분 실행으로 확인한 작업은 확인이 끝나면 0 2 * * * 같은 운영 주기로 되돌림
#안 될 때 점검 8단계
| 순서 | 확인할 것 | 명령 |
|---|---|---|
| 1 | crond가 켜져 있나 | systemctl status crond |
| 2 | 작업이 등록됐나 | crontab -l |
| 3 | 시간 필드가 맞나 | 분, 시 순서, */n 오해 |
| 4 | 손으로 실행되나 | ./dba_check.sh |
| 5 | 환경변수 문제인가 | PATH, ORACLE_HOME, ORACLE_SID |
| 6 | 실행 권한이 있나 | ls -l dba_check.sh의 x |
| 7 | %를 이스케이프했나 |
crontab 줄의 date +\%Y |
| 8 | 로그에 무엇이 남았나 | journalctl -u crond, 스크립트 로그 |
수업의 종합 문제는 1~4단계가 모두 정상인데 로그가 남지 않는 경우이며, 다음으로 볼 곳은 5단계 환경변수임
손으로 실행할 때는 로그인 셸의 .bash_profile 덕분에 되던 것이 cron에서는 안 되는 경우가 가장 흔함
#사용 조건과 주의사항
백업, 점검 작업은 로그를 남기고, 로그가 정상인지 주기적으로 확인해야 누락을 알아챔
cron 등록만으로 작업 성공이 보장되지 않음
같은 작업이 오래 걸려 다음 주기와 겹치면 동시에 두 번 돌 수 있으므로, 실행 시간이 긴 작업은 주기와 잠금(flock 등)을 함께 정함
스크립트에 DB 비밀번호를 적지 않고 / as sysdba 같은 OS 인증을 씀