Devin.KR
로그인

리눅스 date 명령어 사용법 - 타임스탬프 포매팅과 타임존, 에폭 변환

개발자 조회 1

이 명령어를 언제 쓰는가

백업 파일 이름에 날짜를 붙일 때, 로그의 에폭 초를 사람이 읽는 시각으로 바꿀 때, 어제 날짜로 된 로그를 찾아야 할 때 date를 쓴다. 인자 없이 치면 현재 시각을 찍는 단순한 명령이지만, 실무에서 값어치가 나는 부분은 포맷 지정자타임존 처리다.

장애 분석에서 date를 정확히 다루는 것은 생각보다 중요하다. 애플리케이션 로그는 KST인데 액세스 로그는 UTC이고 클라우드 콘솔은 또 다른 타임존이면, 사건 순서를 잘못 읽어 원인을 엉뚱한 데서 찾게 된다.

기본 형식

date [옵션] [+포맷]
  • +포맷 — 반드시 +로 시작한다. % 지정자와 일반 문자를 섞어 쓴다. 공백이 들어가면 따옴표로 감싼다.
  • 옵션 — 기준 시각을 바꾸거나(-d, -r) 타임존을 바꾼다(-u). 이 부분이 GNU와 BSD에서 크게 갈린다.

자주 쓰는 포맷 지정자

지정자의미출력 예
%Y %m %d4자리 연도 / 2자리 월 / 2자리 일2026 08 25
%H %M %S24시간 시 / 분 / 초22 19 02
%F%Y-%m-%d의 축약2026-08-25
%T%H:%M:%S의 축약22:19:02
%s유닉스 에폭 초1787663942
%j연중 일수(001~366)237
%a %b요일·월 약어. 로케일 영향을 받는다Tue Aug
%Z %z타임존 이름 / UTC 오프셋KST +0900
%N나노초. GNU는 %3N으로 밀리초210899000

자주 쓰는 옵션

옵션의미비고
-uUTC 기준으로 출력GNU·BSD 공통
-d 문자열지정한 시각을 기준으로 계산GNU 전용
-r 파일파일의 수정 시각GNU. BSD에서는 에폭 초를 받는다
-v ±값시각을 가감BSD 전용
-j -f 입력서식문자열을 파싱만 하고 시계는 안 건드림BSD 전용
-RRFC 5322 형식Tue, 25 Aug 2026 22:19:02 +0900
-I[단위]ISO 8601 형식date -Iseconds → 2026-08-25T22:19:02+09:00

실전 예제

1) 백업 파일 이름에 타임스탬프를 붙인다. 가장 많이 쓰는 형태다. 콜론과 공백은 파일명에 부적합하니 넣지 않는다.

TS=$(date +%Y%m%d_%H%M%S)
mysqldump --single-transaction shopdb > "/backup/shopdb_${TS}.sql"

실제 값은 shopdb_20260825_221902.sql 형태가 된다. 파일명에는 %F보다 %Y%m%d가 무난하다. 하이픈이 없으면 정렬과 find -name 패턴이 단순해진다.

2) 어제 날짜로 된 로그를 처리한다. 크론에서 전날 로그를 집계하는 전형적인 패턴이다.

YDAY=$(date -d 'yesterday' +%Y-%m-%d)
zgrep ' 500 ' "/var/log/nginx/access-${YDAY}.log.gz" | wc -l

-d에는 yesterday, tomorrow, -7 days, next monday, 2 hours ago, last month 같은 표현이 들어간다. 이건 GNU date의 기능이라 맥에서는 동작하지 않는다.

3) 에폭 초를 사람이 읽는 시각으로 바꾼다. JSON 로그나 DB의 created_at이 에폭으로 저장돼 있을 때 쓴다.

date -d @1787663942 '+%F %T %Z'      # GNU
date -r 1787663942 '+%F %T %Z'       # BSD/macOS
2026-08-25 22:19:02 KST

4) 로그의 UTC 시각을 KST로 맞춰 본다. 액세스 로그는 UTC, 애플리케이션 로그는 KST인 흔한 상황이다. TZ 환경변수를 명령 앞에 붙이면 그 명령에만 적용된다.

TZ=UTC date '+%F %T %Z'
TZ=Asia/Seoul date '+%F %T %Z'
2026-08-25 13:19:02 UTC
2026-08-25 22:19:02 KST

5) 특정 시각의 에폭 값을 구해 범위 조회에 쓴다. 장애 시간대만 잘라낼 때다.

# GNU
FROM=$(date -d '2026-08-25 14:00:00' +%s)
TO=$(date -d '2026-08-25 15:00:00' +%s)

# BSD/macOS
FROM=$(date -j -f '%Y-%m-%d %H:%M:%S' '2026-08-25 14:00:00' +%s)

6) 로그 한 줄에 표준 형식의 시각을 남긴다. 여러 시스템의 로그를 나중에 합칠 생각이라면 ISO 8601에 타임존까지 붙이는 것이 안전하다.

echo "$(date -Iseconds) deploy started rev=$(git rev-parse --short HEAD)"
2026-08-25T22:19:02+09:00 deploy started rev=a1b2c3d

함정과 주의점

%M%m을 바꿔 쓰는 실수가 정말 잦다. 대문자 %M이 분, 소문자 %m이 월이다. date +%Y-%M-%d는 오류 없이 조용히 2026-19-25 같은 값을 만든다. 파일명이 하루 종일 이상하게 쌓인 뒤에야 발견된다. 날짜만 필요하면 %F, 시각만 필요하면 %T를 쓰는 습관이 실수를 줄인다.

GNU와 BSD의 옵션이 호환되지 않는다. 맥에서 짠 스크립트를 리눅스 서버에 올리면(또는 그 반대) date 부분이 먼저 깨진다. date -d 'yesterday'는 맥에서 date: illegal option -- d가 뜨고, date -v-1d는 리눅스에서 통하지 않는다. 양쪽에서 돌아야 하는 스크립트라면 분기하거나, 맥에 brew install coreutilsgdate를 넣어 쓴다.

BSD의 -j -f는 빠진 필드를 현재 시각으로 채운다. 가장 조용히 틀리는 함정이다. 맥에서 date -j -f '%Y-%m-%d' '2026-01-15' +%s를 실행하면 2026년 1월 15일 00시 00분이 아니라 지금 시각의 시·분·초가 붙은 값이 나온다. 날짜만 파싱할 때도 date -j -f '%Y-%m-%d %H:%M:%S' '2026-01-15 00:00:00' +%s처럼 시각을 명시해야 한다.

로케일 때문에 파싱이 깨진다. %a, %b는 로케일을 따른다. 한국어 로케일에서는 date '+%a %b'화 8월로 나온다. 로그 파일명이나 grep 패턴을 만드는 자리라면 LC_ALL=C date ...로 로케일을 고정해 항상 Tue Aug가 나오게 한다. 크론은 로케일 환경이 대화형 셸과 다르므로 특히 주의한다.

date로 시스템 시각을 바꾸지 마라. date -sdate 082522192026으로 시각을 직접 설정하면 NTP·chrony와 충돌하고, 시간이 갑자기 뒤로 점프하면서 DB 복제나 인증서 검증, 클러스터의 리더 선출이 한꺼번에 무너질 수 있다. 요즘 리눅스에서 시각과 타임존은 timedatectl이 담당한다.

timedatectl                                # 현재 시각·타임존·NTP 동기 상태
sudo timedatectl set-timezone Asia/Seoul
sudo timedatectl set-ntp true
chronyc tracking                           # 동기화 오차 확인

서버 타임존은 UTC로 두는 편이 관리가 쉽다. 여러 리전에 서버가 흩어져 있다면 시스템 타임존을 전부 UTC로 통일하고 표시 단계에서만 변환하는 방식이 로그 대조 사고를 줄인다. 이미 KST로 운영 중인 시스템을 도중에 바꾸면 로그 시각이 9시간 튀므로, 바꿀 때는 반드시 그 사실을 문서에 남긴다.

함께 보면 좋은 명령어

  • touchtouch -t 또는 touch -d로 파일 시각을 지정한 뒤 find -newer와 조합하면 기간별 파일 추출이 간단해진다.
  • crontab — 크론이 만드는 로그 파일명에 date를 쓸 때는 %\%로 이스케이프해야 한다는 점을 기억한다.
  • uptime — 시각이 아니라 부팅 이후 경과 시간이 필요할 때 쓴다.