메일 발송 서버 주소를 바꿨다. 설정 파일을 고치고 다시 띄웠는데 옛 주소로 나간다. 파일을 다시 봐도 새 주소가 맞게 들어가 있었다.
Table of contents
Open Table of contents
원인 — 값을 만드는 자리가 둘이었다
서버에 들어가서 실제 설정 파일을 봤다.
$ cat /etc/app/mail.conf
smtp.host=mail-old
smtp.host 가 옛 주소였다. 내가 고친 것은 소스의 설정 파일이었고 /etc/app/mail.conf 는 기동 스크립트가 만들고 있었다.
cat > /etc/app/mail.conf <<EOT
smtp.host=${SMTP_HOST:-mail-old}
smtp.port=${SMTP_PORT:-25}
EOT
SMTP_HOST 가 있으면 그 값을, 없으면 기본값을 쓴다. 환경 변수가 안 들어가 있어서 기본값이 나갔다.
같은 값이 두 군데서 만들어지고 나중에 만들어진 쪽이 이긴다. 파일도 맞고 코드도 맞는데 결과만 틀린 상태라 어느 한쪽만 보면 이유를 알 수 없다.
어느 쪽이 진짜인지 정했다
두 곳을 다 유지하는 방법도 있지만 헷갈려서 하나를 없앴다. SMTP_HOST 를 밖에서 주는 쪽만 남긴 것이다. 기동 스크립트가 만드는 쪽을 남기고 소스의 설정 파일은 지웠다. 서버마다 값이 달라야 하니 밖에서 넣는 쪽이 맞았다.
지우면서 예시 파일만 남겼다.
config/mail.conf.sample
값이 어디서 오는지 주석으로 적었다.
# 이 파일은 예시다. 실제 값은 기동 스크립트가 환경 변수로 만든다.
# SMTP_HOST, SMTP_PORT
smtp.host=
smtp.port=
같은 방식으로 다른 설정도 훑어봤다.
$ ls /etc/app/
db.conf mail.conf pay.conf upload.conf
각각 누가 만드는지 찾아 표로 적었다.
| 파일 | 만드는 곳 |
|---|---|
| db.conf | 기동 스크립트 |
| mail.conf | 기동 스크립트 |
| pay.conf | 소스에 있음 + 기동 스크립트도 만듦 |
| upload.conf | 소스에 있음 |
pay.conf 가 mail.conf 와 같은 상태였다. 결제 설정이라 더 나빴을 수 있다. upload.conf 는 소스에만 있는데 환경마다 다른 업로드 경로가 들어 있어서 이것도 옮겨야 했다.
기본값이 조용히 이긴다
${SMTP_HOST:-mail-old} 형태에는 함정이 있었다. 환경 변수를 안 넣으면 기본값이 쓰이고 오류가 안 난다. 넣었다고 생각하고 넘어가면 옛 주소로 계속 나간다.
기본값을 두는 것이 나쁜 것은 아니다. 다만 넣어야 하는 값과 없어도 되는 값을 나눠야 했다.
: "${SMTP_HOST:?SMTP_HOST 가 설정되지 않았습니다}"
: "${SMTP_PORT:=25}"
:? 는 없으면 멈추고 := 는 기본값을 쓴다. 주소는 서버마다 달라야 하니 앞이고 포트는 대개 같으니 뒤다.
SMTP_HOST 처럼 틀리면 밖으로 나가는 값은 없을 때 아예 안 뜨는 편이 낫다. 조용히 잘못 나가는 것보다 안 뜨는 것이 빨리 드러난다.
검증 — 만들어진 결과
기동 스크립트가 파일을 만든 뒤 그 결과를 로그에 남기게 했다.
echo "[설정] $(grep -v '^#' /etc/app/mail.conf | tr '\n' ' ')"
[설정] smtp.host=mail-new smtp.port=25
grep -v 로 주석을 걷어 한 줄로 찍으니 파일을 열어 볼 필요가 없다. 비밀번호가 들어가는 파일이면 값을 찍으면 안 되니 키 이름만 찍었다.
echo "[설정] 키: $(grep -o '^[a-z.]*' /etc/app/db.conf | tr '\n' ' ')"
배포 뒤에 한 번 보는 것도 넣었다.
for f in db mail pay upload; do
echo "--- $f ---"
grep -v '^#' /etc/app/$f.conf | grep -v '^$'
done
db.conf 와 pay.conf 까지 값이 비어 있거나 옛 것이면 이 출력에서 보인다. 띄우기 전에 보는 것이 아니라 띄운 뒤에 본다. 만들어진 결과를 봐야지 만들 예정인 것을 보면 소용없다.
정리
- 같은 값을 만드는 자리가 둘이면 나중에 만든 쪽이 이긴다
- 파일도 맞고 코드도 맞는데 결과만 틀릴 수 있다
- 어느 쪽이 진짜인지 정하고 나머지는 없앤다
- 예시 파일만 남기고 값이 어디서 오는지 적는다
- 기본값은 조용히 이긴다. 없으면 멈출 값과 없어도 되는 값을 나눈다
- 만들어진 결과를 기동 로그에 찍는다. 비밀이 있으면 키 이름만 찍는다
- 설정 파일이 여럿이면 각각 누가 만드는지 표로 정리한다
- 확인은 띄운 뒤에 한다. 만들어질 예정인 것 말고 만들어진 것을 본다