옛 함수를 전부 새 함수로 바꾸는 작업을 했다. 다 바꿨는지 확인하려고 검색을 돌렸다.
$ grep -r "old_encrypt" src/
$
아무것도 안 나와서 끝난 것으로 보고 배포했다. 일주일 뒤에 그 함수를 부르는 자리에서 오류가 났다.
Table of contents
Open Table of contents
검색이 아무것도 안 봤다
다시 돌려 봤다.
$ grep -r "old_encrypt" src/
src/legacy/auth_old.php: return old_encrypt($pw);
이번에는 나온다. 처음에 왜 안 나왔는지 보니 grep 을 친 위치가 달랐다. src/ 가 아니라 다른 디렉터리에서 쳤고 그 아래에는 .php 파일이 아예 없었다.
대상이 비어 있으면 grep 은 0건을 낸다. 없다는 결과와 안 봤다는 결과의 출력이 똑같다. 화면만 보고는 둘을 구분할 방법이 없었다.
검증 — 통과가 나오면 대조군을 돌렸다
그 뒤로 검색이 0건이면 한 번 더 돌리게 됐다. 반드시 나와야 하는 낱말로 같은 명령을 친다.
$ grep -rl "function" src/ | head -3
src/controllers/product.php
src/models/order_model.php
src/helpers/common_helper.php
이게 나오면 grep 이 실제로 파일을 보고 있다는 뜻이다. 대조군에서도 아무것도 안 나오면 대상이 비어 있거나 경로가 틀린 것이다.
통과가 나왔을 때 실패해야 하는 입력으로 한 번 돌려 보는 것이 요령이었다. 같은 출력이 나오면 그 검사는 아무것도 가르지 못한 것이다.
대상 개수를 같이 셌다
더 간단한 방법은 몇 개를 봤는지 세는 것이었다.
$ find src/ -name "*.php" | wc -l
284
$ grep -rl "old_encrypt" src/ --include=*.php | wc -l
0
284개를 보고 0개가 걸렸다. 이건 없는 것이다.
$ find src/ -name "*.php" | wc -l
0
이러면 안 본 것이다. wc -l 한 줄을 더 치는 것으로 두 상황이 갈렸다. 결과만 보지 않고 모수를 함께 보면 오해가 줄었다.
매번 손으로 치면 빠뜨려서 확인할 것을 스크립트로 묶었다.
#!/bin/sh
TARGET=src
PATTERN=old_encrypt
TOTAL=$(find "$TARGET" -name "*.php" | wc -l)
if [ "$TOTAL" -eq 0 ]; then
echo "대상 파일이 0개입니다. 경로 확인: $TARGET"
exit 1
fi
HIT=$(grep -rl "$PATTERN" "$TARGET" --include=*.php | wc -l)
echo "대상 ${TOTAL}개 중 ${HIT}개에서 발견"
[ "$HIT" -eq 0 ] && echo "OK" || grep -rn "$PATTERN" "$TARGET" --include=*.php
TOTAL 이 0이면 실패한다. 이게 핵심이다.
같은 함정이 있던 자리들
이 문제가 검색만 있는 것이 아니었다. rsync -n 으로 무엇이 바뀔지 볼 때 -v 가 없으면 목록이 안 나온다.
$ rsync -avn --delete src/ server:/path/
빈 출력이 바뀔 것이 없다는 뜻으로 보이지만 실제로는 아무것도 출력하지 않은 것이다.
find 가 기본으로 심볼릭 링크를 안 따라가는 것도 같은 함정이었다. 링크 아래를 검사하려면 -L 이 필요하다.
$ find -L src/ -name "*.php"
조회 조건이 너무 좁아 0건이 나오는 경우도 있었다.
SELECT COUNT(*) FROM product WHERE reg_date >= '2014-01-18' AND use_yn = 'Y';
-- 0
날짜 조건 때문인지 정말 없는 것인지 구분하려면 조건을 하나씩 빼 보면 된다.
SELECT COUNT(*) FROM product WHERE reg_date >= '2014-01-18'; -- 3
SELECT COUNT(*) FROM product WHERE use_yn = 'Y'; -- 4128
옮긴 뒤 서버에서도 같은 검색을 했다.
$ ssh deploy@server 'grep -rl "old_encrypt" /var/www/shop --include=*.php | wc -l'
내 작업 사본과 서버가 항상 같지는 않다. 배포 제외 목록에 든 디렉터리가 있었다.
정리
- 대상이 비어 있으면
grep은 0건을 낸다 - 없다는 결과와 안 봤다는 결과의 출력이 같다
- 통과가 나오면 나와야 하는 입력으로 한 번 더 돌린다
- 같은 출력이 나오면 그 검사는 아무것도 가르지 못한 것이다
find ... | wc -l로 몇 개를 봤는지 함께 센다- 결과만 보지 않고 모수를 본다
rsync -n에-v가 빠지면 아무것도 출력하지 않는다find는-L이 없으면 심볼릭 링크 아래를 안 본다- 조회가 0건이면 조건을 하나씩 빼 본다
- 확인 스크립트는 대상이 0개일 때 실패로 끝나게 한다
- 작업 사본에서 통과해도 서버에서 다시 확인한다