LFCS — Linux Foundation System Administrator
When Does the Shell Do It For You
한국어 원문으로 표시합니다.
한 줄 요약
시험에서 명령이 예상과 다르게 동작하는 이유의 대부분은 명령이 아니라 셸이 명령을 실행하기 전에 한 일 때문이다. 확장 시점, 파일 디스크립터, find 의 표현식 문법 — 이 세 가지가 필수 명령 영역의 뼈대다.
왜 이게 필요했나
rm -f /var/log/*.gz 를 실행했는데 파일이 지워지지 않는다. rm 을 의심하지만 범인은 rm 이 아니다. 와일드카드를 실제 파일 목록으로 바꾸는 주체는 셸이고, 셸은 명령을 부르기 전에 그 일을 끝낸다. 매칭되는 파일이 없으면 셸은 *.gz 라는 글자 그대로를 인자로 넘겨 버리고, rm 은 그런 이름의 파일이 없다고 답한다.
따옴표의 의미도 여기서 갈린다. 큰따옴표는 변수 확장은 살리고 단어 분리와 파일명 확장만 막는다. 작은따옴표는 전부 막는다. 공백이 들어간 경로를 다룰 때 큰따옴표를 빠뜨리면 인자 하나가 두 개로 쪼개진다. 시험에서 경로에 공백이 있는 문제가 나오는 이유가 이것이다.
어떻게 동작하나
리다이렉션은 파일 디스크립터 조작이다. 모든 프로세스는 0(표준 입력), 1(표준 출력), 2(표준 오류)를 갖고 시작한다. > out.txt 는 "1번 디스크립터가 가리키는 곳을 이 파일로 바꿔라" 라는 뜻이고, 2>&1 은 "2번을 지금 1번이 가리키는 곳과 같은 곳으로 복제하라" 라는 뜻이다.
순서가 중요한 이유가 바로 이 '지금' 이다.
| 표기 | 결과 |
|---|---|
cmd > f 2>&1 |
1번을 f 로 바꾼 뒤 2번을 f 로 복제 → 둘 다 파일 |
cmd 2>&1 > f |
2번을 터미널로 복제한 뒤 1번만 f 로 바꿈 → 오류는 화면 |
find 는 명령이 아니라 표현식 언어다. -name, -size, -mtime, -perm 은 옵션이 아니라 참/거짓을 돌려주는 술어이고, 나열하면 암묵적 AND 로 이어진다. -print 나 -exec 도 술어이며 부수 효과가 있는 술어일 뿐이다. 그래서 -o 로 OR 를 쓸 때 괄호를 빠뜨리면 우선순위가 어긋나 엉뚱한 파일이 잡힌다.
숫자 인자에는 부호 규칙이 붙는다. -mtime 30 은 "정확히 30일 전 구간", -mtime +30 은 "30일보다 더 오래된", -mtime -30 은 "30일 이내" 다. -perm 644 는 정확히 일치, -perm -644 는 그 비트를 모두 포함, -perm /644 는 그중 하나라도 포함이다. 시험에서 가장 많이 깎이는 지점이다.
현장에서 만나는 모습
저자가 정리한 파일 디스크립터 글에는 이런 사례가 나온다. 로그 파일을 실수로 지웠는데, 그 파일을 열고 있던 프로세스가 아직 살아 있었다. 디렉터리 엔트리는 사라졌지만 링크 수가 0 이 되어도 열린 디스크립터가 남아 있으면 커널은 블록을 회수하지 않는다. 그래서 /proc/<PID>/fd/<번호> 를 그대로 복사하는 것만으로 내용을 되살릴 수 있었다. 반대로 같은 성질을 이용해 truncate -s 0 /proc/<PID>/fd/<번호> 로 프로세스를 살린 채 공간만 비울 수도 있는데, 번호를 잘못 짚으면 멀쩡한 파일이 날아간다.
파이프라인에서는 yes | head -1 이 교과서다. head 가 먼저 끝나면 yes 는 읽는 쪽이 없는 파이프에 쓰다가 SIGPIPE 로 죽는다. 이것이 정상 동작이다. 그리고 저자의 셸 글이 반복해서 강조하는 원칙 하나 — ls 출력을 파싱하지 말고 글롭으로 순회하라. 파일 이름에 공백이나 개행이 들어가는 순간 ls 파싱은 조용히 틀린다.
시험장에서 손이 굳지 않게
LFCS 는 두 시간에 과제를 손으로 푸는 시험이라, 아는 것과 제한 시간 안에 치는 것이 다르다. 몇 가지만 몸에 익혀 두면 시간이 크게 줄어든다.
문서를 어디서 볼지 정해 둔다. 인터넷은 없지만 man 과 --help 는 있다.
man 안에서 / 로 찾고 n 으로 다음으로 넘어가는 것만 익혀도 옵션 하나를
찾는 데 몇 초면 된다. 그리고 man -k 로 낱말에서 명령을 거꾸로 찾을 수 있다는
것을 모르면, 이름이 기억나지 않는 명령 하나에 몇 분을 쓴다.
되돌릴 수 없는 것을 먼저 확인한다. rm·mkfs·dd·> 는 물어보지 않는다.
특히 리다이렉션은 명령을 치는 순간 대상 파일을 먼저 비운다. 그래서 원본을
읽어 같은 파일에 쓰는 형태는 언제나 내용을 날린다. 중간 파일을 거치거나
제자리 편집 옵션을 쓴다.
바꾸기 전에 사본을 뜬다. 설정 파일을 고칠 때 날짜를 붙여 하나 복사해 두는 데 2초가 걸리고, 그것이 없으면 되돌리는 데 몇 분이 간다. 시험에서도 실무에서도 같다.
확인까지가 한 과제다. 서비스를 켜라는 과제는 지금 도는 것과 재부팅 뒤에도 뜨는 것이 다른 설정이고, 둘 다 물어본다. 사용자를 만들라는 과제는 셸과 홈 디렉터리와 그룹까지가 보통 포함된다. 답을 냈다고 생각한 자리에서 한 번 더 확인하는 30초가, 다 풀고 나서 틀린 것을 찾는 것보다 훨씬 싸다.
마지막으로 막히면 넘어간다. 부분 점수제이므로 한 과제에 매달리는 동안 풀 수 있었던 두 과제가 지나간다. 넘어갈 때는 무엇을 남겨 뒀는지 적어 두고, 시간이 남으면 돌아온다.
다음 실습에서 할 것
/root/lfcs-ess/ 에 디렉터리 트리를 세우고 하드 링크와 심볼릭 링크의 inode 차이를 직접 확인한다. find 를 크기·시각·권한 조건으로 조합해 목록을 뽑고, 같은 디렉터리를 gzip 과 xz 로 각각 압축해 크기를 비교한다. 마지막에는 diff -u 로 패치를 만들어 사본에 적용한다. 그다음 실습에서는 직접 만든 로그를 grep·sed·awk·jq·yq 로 가공한다.