문서에 적힌 경로로 갔더니 아무것도 없었다.
Table of contents
Open Table of contents
증상 — 문서가 달랐다
문서에는 이렇게 적혀 있었다.
배포 경로 /var/www/html
로그 /var/log/app
설정 /etc/app
장비는 맞았고 /var/www/html 만 비어 있었다.
$ ps -ef | grep php-fpm
... php-fpm: pool app
$ ls -l /proc/$(pgrep -f "php-fpm: pool app" | head -1)/cwd
lrwxrwxrwx ... -> /srv/elearn/current
/srv/elearn/current 였고 문서와 달랐다.
어느 시점에 배포 경로 가 옮겨졌는데 문서가 안 따라온 것이다. find 로 서버 전체를 뒤지는 방법도 있지만 그것은 시간이 너무 오래 걸린다.
검증 — 도는 것에서 찾았다
문서를 믿지 않고 실제로 도는 프로세스에서 찾았다.
# 작업 디렉터리
$ ls -l /proc/<PID>/cwd
# 열어 놓은 파일
$ ls -l /proc/<PID>/fd | grep -v socket
# 실행 명령
$ tr '\0' ' ' < /proc/<PID>/cmdline
로그 파일도 fd 로 찾았다.
/proc/2841/fd/2 -> /srv/elearn/shared/logs/app.log
/var/log/app 이 아니었다.
설정 파일은 php --ini 처럼 도구가 알려 주기도 했다.
$ php --ini
Loaded Configuration File: /etc/php/7.2/fpm/php.ini
Scan for additional .ini files in: /etc/php/7.2/fpm/conf.d
$ nginx -T | grep -E "server_name|root|access_log" | head -20
nginx -T 로 실제 로드된 것을 봤는데 파일을 열어 보는 것과 다를 수 있다.
결과 — 문서와 실제의 대응표
찾은 실제 경로를 문서 값과 나란히 적었다.
항목 문서 실제
배포 /var/www/html /srv/elearn/current (심링크 → releases/<날짜>)
로그 /var/log/app /srv/elearn/shared/logs
설정 /etc/app /srv/elearn/shared/config
업로드 /var/www/upload /mnt/nas/upload (마운트)
임시 /tmp /srv/elearn/shared/tmp
문서 열만 고치지 않고 둘을 다 남겼다.
낡은 문서를 보고 온 사람이 그 표에서 대조할 수 있어야 하기 때문이다. 옛 경로를 지우면 그 문서를 이미 읽은 사람은 자기가 아는 경로가 왜 없는지를 모른다.
배경 — 경로가 바뀐 경위
경로가 왜 달라졌는지도 봤다.
2017 /var/www/html 에 직접 배포
2018 판별 폴더 + 심링크 방식으로 변경 ← 문서 미반영
배포 방식이 바뀌면서 경로가 바뀌었는데 문서는 안 고쳤다.
바꾼 사람은 알고 있었지만 적지 않았다. 그 사람이 없어지고 나서 아무도 몰랐다.
주의 — 심링크와 마운트
current 는 실제 자리가 아니라 심링크였다.
$ ls -l /srv/elearn/current
lrwxrwxrwx ... current -> /srv/elearn/releases/20190902_141022
releases 아래를 가리키므로 그 구조를 함께 적었다.
/srv/elearn/
current -> releases/<배포시각> 현재 도는 판
releases/ 최근 5개 보관
shared/ 배포마다 안 바뀌는 것
config/
logs/
tmp/
배포마다 지워지는 것과 아닌 것을 나눈 구조였다.
mount 도 확인했다.
$ mount | grep upload
10.0.0.50:/export/upload on /mnt/nas/upload type nfs4 (rw,...)
업로드 폴더가 nfs4 로 붙은 다른 장비라 그쪽이 죽으면 업로드가 안 된다.
/mnt/nas/upload NFS. 10.0.0.50 의 /export/upload
이 장비가 죽으면 업로드·조회 불가
의존하는 장비도 함께 적었는데 경로만 적으면 그것이 어디 있는지 모른다.
재발 방지 — 자동 추출과 권한
실제 경로를 뽑는 스크립트를 뒀다.
#!/bin/sh
pid=$(pgrep -f "php-fpm: pool app" | head -1)
echo "실행 경로: $(readlink /proc/$pid/cwd)"
echo "설정: $(php --ini | grep Loaded | cut -d: -f2)"
echo "로그: $(readlink /proc/$pid/fd/2)"
mount | grep -E "nfs|cifs"
한 번 돌리면 cwd 와 설정과 로그 경로가 나오므로 문서가 낡아도 된다.
경로별 권한도 같이 적었다. 경로를 알아도 접근이 안 되는 경우가 있었다.
$ ls -ld /srv/elearn/shared/logs
drwxr-x--- 2 www-data www-data ...
경로 소유 권한 접근 계정
/srv/elearn/current deploy 755 누구나 읽기
/srv/elearn/shared/logs www-data 750 www-data, 그룹
/srv/elearn/shared/config www-data 700 www-data 만
권한까지 적으니 왜 안 보이는지를 안 물었다.
로그를 봐야 하는 사람을 어느 그룹에 넣으면 되는지도 이 표로 갈렸다. 사람이 손으로 갱신하는 문서는 결국 낡는다.
정리
- 문서의 경로와 실제가 다르면 실제를 적는다
- 뒤지는 것보다 도는 프로세스에게 묻는 쪽이 빠르다
- 작업 디렉터리와 열어 놓은 파일과 실행 명령을 본다
- 도구가 실제 로드된 설정을 알려 주기도 한다
- 문서와 실제를 나란히 적는다
- 옛 문서를 보고 온 사람이 대조할 수 있어야 한다
- 왜 달라졌는지 본다
- 심링크가 가리키는 곳과 구조의 이유를 적는다
- 마운트된 것은 어느 장비인지 적는다
- 실제 경로를 자동으로 뽑는 스크립트를 둔다
- 권한과 소유자도 함께 적는다