설정 파일을 고쳤는데 몇 분 뒤에 원래대로 돌아가 있었다. 다시 고쳤는데 또 돌아갔다.
Table of contents
Open Table of contents
나중에 쓴 쪽이 이겼다
서버에 직접 붙어서 고치고 있었다.
$ vi /app/config/db.php
다른 사람도 같은 시간에 붙어 있었다.
$ w
USER TTY FROM LOGIN@
... pts/0 web01 14:02
... pts/1 web02 14:05
vim 은 .swp 를 만들어 이미 열려 있으면 알려 주는데 계정이 서로 달라 그 경고가 안 떴다. 각자 자기가 열었던 시점의 내용에 자기 수정을 얹어서 저장하니 나중에 저장한 쪽이 앞의 수정을 통째로 덮는다.
오류도 경고도 없이 조용히 사라진다. 내가 고친 것이 없어졌는데 무엇을 고쳤는지 기억이 안 났다.
$ ls -la /app/config/
-rw-r--r-- 1 ... db.php
백업이 없었다.
vim 이 만드는 .swp 도 저장하면서 사라진 뒤였다. 무엇이 덮였는지는 양쪽 기억을 맞춰 보고 나서야 겨우 알았다. 기억에 기대야 하는 상태가 문제였다.
서버에서 직접 고치는 것을 줄였다
근본은 서버에서 직접 고치는 것이었다.
설정 파일을 SVN 에 넣고 배포로 올린다.
서버에서 직접 고치지 않는다.
SVN 에 넣으면 동시에 고쳐도 합칠 때 드러난다. 그런데 운영 설정에는 비밀번호가 들어 있어서 통째로는 못 넣었다.
// db.php - SVN 에 넣는다
$config['db_host'] = getenv('DB_HOST') ?: 'localhost';
$config['db_pass'] = getenv('DB_PASS') ?: '';
getenv 로 값은 밖에서 받고 구조만 넣었다.
값을 바꾸는 일은 드물고 구조를 바꾸는 일이 잦았기 때문이다. 자주 고치는 쪽을 SVN 이력이 남는 자리로 옮긴 것이다. DB_PASS 처럼 서버에만 두는 값은 그만큼 줄었다.
조치 — 고치기 전에 사본을 떴다
값을 바꿔야 할 때가 있다. 그때 흔적이 남게 했다.
#!/bin/sh
# edit-config.sh
f="$1"
cp "$f" "/backup/config/$(basename $f).$(date +%Y%m%d_%H%M%S).$(whoami)"
vi "$f"
edit-config.sh 가 고치기 전에 복사해 두니 누가 언제 고쳤는지가 파일 이름에 남는다.
$ ls /backup/config/
db.php.20140621_140233.deploy
db.php.20140621_140512.deploy
두 개가 3분 차이로 있었다. 둘이 같이 고쳤다는 것이 이걸로 보인다.
무엇이 바뀌었는지도 볼 수 있게 됐다.
$ diff /backup/config/db.php.20140621_140233.deploy /app/config/db.php
diff 로 지금 것과 이전 것을 비교하면 무엇이 언제 바뀌었는지가 보인다.
/backup/config 에 한 달치를 남기고 지웠는데 설정 파일은 작아서 부담이 없었다. 규칙 하나를 지키는 비용이 사고 하나를 조사하는 비용보다 훨씬 작았다.
잠금 대신 되찾을 수 있게
파일 잠금을 만들 수도 있었다.
# 잠그고 고친다
flock /var/lock/config.lock vi "$f"
만들다가 그만뒀다. flock 으로 잠근 채로 편집기를 켜 두고 점심을 먹으러 가면 아무도 못 고친다. 잠금을 걸면 푸는 것도 다뤄야 하는데 하루에 몇 번 안 고치는 파일에 그것까지 만들 이유가 없었다.
대신 붙었을 때 누가 있는지 보게 안내했다.
$ cat /etc/motd
현재 접속자를 확인하십시오: w
설정 파일은 edit-config.sh 로 고칩니다.
완벽하지는 않지만 없는 것보다 나았다.
사본이 있으니 덮여도 되찾을 수 있다는 것이 잠금을 안 만든 이유였다. flock 으로 막는 쪽과 사본으로 되찾는 쪽 중에 뒤쪽이 이 빈도에는 맞았다.
정리
- 같은 파일을 동시에 고치면 나중에 쓴 쪽이 이긴다
vim의.swp경고는 계정이 다르면 안 뜬다- 오류도 경고도 없이 조용히 덮인다
- 근본은 서버에서 직접 고치는 것이다. 배포로 올리게 바꾼다
- 비밀번호 때문에 못 올리면
getenv로 구조와 값을 나눈다 - 직접 고칠 때는 고치기 전에 복사하고 이름에 누가 언제인지 남긴다
diff로 이전 것과 비교하면 무엇이 언제 바뀌었는지 보인다- 잠금을 걸면 푸는 것도 다뤄야 한다. 빈도가 낮으면 되찾을 수 있게 두면 된다