백업 파일 이름에 날짜를 붙이고 보존 기간이 지난 것을 지우는 일은 거의 모든 운영 스크립트에 들어간다. date 의 포맷 문자와 find 의 시간 조건 두 가지만 정확히 알면 된다.
TODAY="$(date +%Y%m%d)" # 20260920
STAMP="$(date +%Y%m%d%H%M)" # 202609201530
ISO="$(date +%Y-%m-%dT%H:%M:%S%z)" # 2026-09-20T15:30:00+0900
주요 포맷 문자는 다음과 같다.
| 문자 | 뜻 |
|---|---|
%Y · %y |
네 자리 연도 · 두 자리 연도 |
%m · %d |
월 · 일 |
%H · %M · %S |
시(24시간) · 분 · 초 |
%j |
연중 일수 |
%s |
유닉스 시각(초) |
%M 은 분이고 %m 은 월이다. 대소문자를 잘못 쓰면 파일명이 조용히 뒤섞인다.
GNU coreutils 의 date 는 -d 로 상대 시각을 계산한다.
date -d '1 day ago' +%Y%m%d
date -d 'yesterday' +%Y%m%d
date -d '7 days ago' +%Y%m%d
date -d '2026-09-20 -1 month' +%Y%m%d
macOS 와 BSD 의 date 는 -d 대신 -v 를 쓴다. 문법이 다르므로 스크립트를 옮길 때 확인이 필요하다.
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/backup/pg"
TODAY="$(date +%Y%m%d)"
OUT="${BACKUP_DIR}/appdb_${TODAY}.dump"
PGPASSWORD="${PGPASSWORD:?PGPASSWORD is required}" \
pg_dump -h 192.168.0.30 -U appuser -Fc appdb -f "${OUT}"
비밀번호는 명령줄에 쓰지 않는다. 명령줄 인자는 ps 로 다른 사용자에게 그대로 보인다. PGPASSWORD 환경 변수나 ~/.pgpass(권한 600)를 쓴다.
# 28일보다 오래된 파일을 찾아서 목록만 본다
find /backup/pg -type f -name '*.dump' -mtime +28 -print
# 확인한 뒤 지운다
find /backup/pg -type f -name '*.dump' -mtime +28 -delete
반드시 -print 로 먼저 확인하고 나서 -delete 를 붙인다. 경로를 잘못 적은 채 바로 지우면 되돌릴 수 없다.
-delete 는 -exec rm {} \; 보다 빠르고 프로세스를 새로 띄우지 않는다. 다만 -delete 는 find 의 다른 조건보다 먼저 평가될 수 있으므로 항상 조건을 모두 적은 뒤 맨 끝에 둔다.
-mtime +28 은 "수정된 지 28일을 완전히 넘긴" 파일이다. 하루 단위로 내림 계산하므로 경계에서 하루 차이가 난다. 정확한 기준이 필요하면 분 단위인 -mmin 이나 기준 파일을 쓰는 -newermt 를 쓴다.
find /backup/pg -type f ! -newermt '28 days ago' -print
-mtime 은 수정 시각이고 -atime 은 접근 시각, -ctime 은 inode 변경 시각이다. 백업 정리는 보통 -mtime 이 맞다. noatime 으로 마운트한 파일시스템에서는 -atime 이 갱신되지 않아 쓸 수 없다.
find /backup/pg -mindepth 1 -type d -empty -delete
# 매일 01시 백업
0 1 * * * /usr/local/bin/pg_backup.sh >> /var/log/pg_backup.log 2>&1
# 매주 월요일 01시
0 1 * * 1 /usr/local/bin/weekly.sh
# 8시간마다 (0, 8, 16시)
0 */8 * * * /usr/local/bin/sync.sh
cron 은 로그인 셸을 거치지 않아 PATH 가 매우 짧다. 스크립트 안에서 명령을 절대경로로 쓰거나 스크립트 첫머리에 PATH 를 명시한다.