Linux와 터미널 기초
계산과학의 작업 환경은 대부분 Linux 터미널이다. SIESTA·VASP 같은 DFT 코드는 GUI 없이 셸에서 실행되고, 계산 서버 접속·로그 감시·입력 수정·결과 회수까지 전부 셸 명령으로 이뤄진다. 이 장은 이 튜토리얼을 따라가는 데 필요한 최소한의 셸 지식을 실전 예제(input.fdf, siesta.out, OUTCAR 등 실제 다루게 될 파일)로 정리한다. 이미 터미널에 익숙하다면 마지막의 자주 쓰는 조합 표만 훑고 넘어가도 된다.
디렉토리 탐색
| 명령 | 역할 |
|---|---|
pwd | 현재 디렉토리 경로 출력 |
ls | 파일 목록 (-l 상세, -lh 사람이 읽는 용량, -ltr 최근 수정 순) |
cd 경로 | 디렉토리 이동 (cd .. 상위, cd ~ 홈, cd - 직전 위치) |
pwd # /home/user/work/ch01-siesta-scf
ls -ltr # 방금 계산이 만든 파일이 목록 맨 아래에 온다
cd ../ch02-bands # 형제 디렉토리로 이동
계산 디렉 토리에서 ls -ltr은 특히 유용하다 — 가장 최근에 갱신된 파일이 마지막 줄에 오므로, 계산이 지금 무엇을 쓰고 있는지 바로 보인다.
파일 조작
| 명령 | 역할 |
|---|---|
mkdir -p 경로 | 디렉토리 생성 (-p는 중간 경로까지 한 번에) |
cp 원본 대상 | 복사 (-r 디렉토리 통째) |
mv 원본 대상 | 이동 또는 이름 변경 |
rm 파일 | 삭제 (-r 디렉토리) |
mkdir -p scan/c_5.16 # 계산 케이스 디렉토리 생성
cp input.fdf input.fdf.bak # 수정 전 백업
mv siesta.out siesta.out.old # 재실행 전 이전 로그 보존
Linux에는 휴지통이 없다. rm으로 지운 파일은 되돌릴 수 없으며, 특히 rm -rf 디렉토리는 확인 없이 트리 전체를 지운다. 며칠 걸린 계산 결과를 명령 한 줄로 잃을 수 있으므로, 삭제 대신 mv old_run/ _archive/처럼 보관 디렉토리로 옮기는 습관이 안전하다. 와일드카드 삭제(rm *.out)는 실행 전에 같은 패턴으로 ls *.out을 먼저 쳐서 대상 목록을 확인한다.
파일 내용 확인
| 명령 | 역할 |
|---|---|
cat 파일 | 전체 출력 — 짧은 파일(입력 파일 확인)용 |
less 파일 | 페이지 단위 열람 — 긴 로그용. /문자열로 검색, G 끝으로, q 종료 |
head -n 20 파일 | 앞 20줄 |
tail -n 20 파일 | 뒤 20줄 |
tail -f 파일 | 파일 끝을 실시간 추적 — 돌고 있는 계산 로그 감시 |
cat input.fdf # 제출 직전 입력 최종 확인
tail -f siesta.out # SCF 반복이 찍히는 것을 실시간으로 본다 (Ctrl-C로 종료)
tail -f는 계산이 정상 진행 중인지 확인하는 가장 기본적인 방법이다. 출력이 몇 분째 멈춰 있다면 무언가 잘못되었을 가능성이 크다.
검색 — grep
grep은 파일에서 패턴이 있는 줄을 뽑는다. 수천 줄에 달하는 계산 로그에서 원하는 수치·경고를 찾는 핵심 도구다.
grep -i "total energy" siesta.out # 대소문자 무시(-i)하고 에너지 라인 검색
grep "SCF cycle converged" siesta.out # 수렴 메시지 존재 확인
grep -in "error" siesta.out # 에러 검색, 줄 번호(-n)까지 표시
grep -c "scf:" siesta.out # SCF 반복 횟수 세기(-c)
grep -A 6 "TOTAL-FORCE" OUTCAR # 매칭 줄과 그 아래 6줄(-A)까지 — VASP 힘 블록
grep -r "MeshCutoff" scan/ # 디렉토리 전체(-r)에서 검색
자주 쓰는 옵션 — -i 대소문자 무시, -n 줄 번호, -c 개수, -A N/-B N 매칭 줄 아래/위 N줄 포함, -r 재귀, -v 매칭 안 되는 줄만.
스트림과 리다이렉트
모든 프로그램은 세 개의 스트림을 갖는다 — 표준 입력(stdin), 표준 출력(stdout), 표준 에러(stderr). 이 튜토리얼의 실행 명령이 정확히 이 구조다.
siesta < input.fdf > siesta.out
< input.fdf— 파일을 stdin으로 연결한다. SIESTA는 입력을 stdin으로 읽는 관례를 따른다.> siesta.out— stdout을 파일로 보낸다(기존 내용은 덮어쓴다).>>는 덮어쓰지 않고 뒤에 이어 붙인다.- stderr는 위 명령에서 여전히 화면으로 나온다. 에러까지 같은 파일에 남기려면
2>&1을 붙인다 — "스트림 2번(stderr)을 1번(stdout)이 가는 곳으로 합쳐라"는 뜻이다.
mpirun -np 4 siesta < input.fdf > siesta.out 2>&1
MPI 실행이나 배치 잡에서는 라이브러리 에러·메모리 부족 메시지가 stderr로만 나오는 경우가 많으므로 2>&1을 붙이는 것이 안전하다.
파이프
|는 앞 명령의 stdout을 뒤 명령의 stdin으로 넘긴다. 작은 명령을 조립해 한 줄 분석을 만든다.
grep "scf:" siesta.out | wc -l # SCF 반복 줄 수 세기 (wc -l = 줄 개수)
grep "E0=" OSZICAR | tail -n 1 # VASP 마지막 이온 스텝 에너지만
grep "Total =" scan/*/siesta.out | sort # 스캔 결과를 케이스명 순으로 정렬
wc -l(줄 수), sort(정렬, -g는 수치 크기순), uniq(중복 제거)가 파이프의 단골 조각이다.
sed — 한 줄 치환
sed는 스트림 편집기다. 입력 파라미터 하나를 바꾼 사본을 만들 때 편집기를 열 필요가 없다.
sed 's/300. Ry/400. Ry/' input.fdf > input_400.fdf # 치환한 사본 생성
sed -i.bak 's/300. Ry/400. Ry/' input.fdf # 제자리 수정, 원본은 .bak으로 백업
diff input.fdf.bak input.fdf # 바뀐 줄만 확인
s/찾을것/바꿀것/ 문법이 기본이고, 줄 끝에 g를 붙이면 한 줄 안의 모든 매칭을 바꾼다. sed -i로 파일을 수정했다면 diff로 의도한 줄만 바뀌었는지 반드시 확인한다 — 패턴이 예상 밖의 줄에도 매칭되는 사고가 흔하다.
셸 변수와 for 루프 — 격자상수 스캔
변수는 이름=값(등호 양옆 공백 없음)으로 정의하고 $이름으로 참조한다. for 루프와 결합하면 파라미터 스캔을 자동화할 수 있다. 챕터 01의 input.fdf에서 cell 길이 5.160000을 자리표시자 __C__로 바꾼 template.fdf를 준비했다고 하자(원자 좌표는 Fractional로 바꿔 두면 cell과 함께 자동으로 스케일된다).
#!/bin/bash
# cell 길이 c 스캔 — template.fdf의 __C__ 를 실제 값으로 치환해 실행
for c in 5.00 5.08 5.16 5.24 5.32; do
dir=c_${c}
mkdir -p ${dir}
sed "s/__C__/${c}/" template.fdf > ${dir}/input.fdf
cp C.psml ${dir}/
(cd ${dir} && siesta < input.fdf > siesta.out)
echo "c = ${c} done"
done
괄호 ( ... )는 서브셸이라 안에서 cd해도 루프가 도는 위치는 바뀌지 않는다. 스캔이 끝나면 결과를 한 줄로 수확한다.
grep "Total =" c_*/siesta.out
아카이브와 전송 — tar, scp, rsync
tar czf ch01_results.tar.gz ch01-siesta-scf/ # 디렉토리를 압축 아카이브로 (c=생성, z=gzip, f=파일명)
tar xzf ch01_results.tar.gz # 풀기 (x=추출)
scp ch01_results.tar.gz user@server:~/work/ # 원격 서버로 복사
rsync -avz user@server:~/work/ch01/ ./ch01/ # 원격 디렉토리 동기화 회수
rsync는 이미 받은 파일을 건너뛰고 바뀐 부분만 전송하므로, 큰 계산 디렉토리를 반복해서 회수할 때 scp보다 낫다. -avz는 아카이브 모드(-a)+전송 목록 출력(-v)+압축 전송(-z)이다. 경로 끝의 / 유무에 따라 "디렉토리 안의 내용"인지 "디렉토리 자체"인지가 달라지므로 처음에는 -n(dry-run)으로 대상 목록을 먼저 확인하는 것이 안전하다.
ssh — 원격 계산 서버
ssh user@server.example.edu # 원격 셸 접속
ssh user@server.example.edu "ls work" # 접속 없이 원격 명령 한 줄 실행
~/.ssh/config에 호스트 별칭·키 설정을 등록해 두면 ssh myserver처럼 짧게 쓸 수 있다. 계정·호스트·인증 방식은 기관마다 다르므로 소속 기관의 안내를 따른다.
로그아웃해도 계산 유지 — nohup과 tmux
ssh 세션에서 그냥 실행한 계산은 접속이 끊기면 함께 종료된다. 두 가지 해법이 있다.
nohup mpirun -np 4 siesta < input.fdf > siesta.out 2>&1 &
nohup은 접속 종료 신호를 무시하게 하고, 끝의 &는 백그라운드로 보낸다. 로그아웃 후 다시 접속해 tail -f siesta.out으로 진행을 확인하면 된다.
tmux는 터미널 세션 자체를 서버에 남겨 두는 도구다.
tmux new -s calc # calc라는 이름의 세션 생성
# (세션 안에서 계산 실행)
# Ctrl-b 누른 뒤 d — 세션을 붙여 둔 채 빠져나오기(detach)
tmux attach -t calc # 재접속 후 세션 복귀
실행 중인 계산을 여러 개 띄워 두고 오가며 확인할 수 있어, 대화형으로 작업하는 계산 서버에서는 tmux 쪽이 편하다. 다만 정식 클러스터에서는 이 방식 대신 배치 스케줄러로 잡을 제출한다 — 챕터 12에서 다룬다.
실행 권한 — chmod +x
셸 스크립트는 실행 권한이 있어야 ./스크립트로 실행할 수 있다.
chmod +x scan.sh
./scan.sh
권한 없이 실행하면 "Permission denied"가 나온다. bash scan.sh처럼 인터프리터를 직접 불러도 되지만, 스크립트 첫 줄의 #!/bin/bash(shebang)와 실행 권한을 갖춰 두는 쪽이 표준 관례다.
자주 쓰는 조합
| 상황 | 한 줄 명령 |
|---|---|
| 돌고 있는 계산 로그 실시간 확인 | tail -f siesta.out |
| SCF가 몇 번 돌았는지 | grep -c "scf:" siesta.out |
| SCF 수렴 여부 확인 | grep "SCF cycle converged" siesta.out |
| SIESTA 최종 에너지 | grep "Total =" siesta.out |
| VASP 마지막 이온 스텝 에너지 | grep "E0=" OSZICAR | tail -n 1 |
| VASP 힘 블록 확인 | grep -A 6 "TOTAL-FORCE" OUTCAR |
| 로그에서 에러·경고 찾기 | grep -in "error" siesta.out |
| 최근에 갱신된 파일 확인 | ls -ltr |
| 파라미터 스캔 결과 수확 | grep "Total =" c_*/siesta.out |
| 입력 파라미터 한 줄 치환(백업 포함) | sed -i.bak 's/300. Ry/400. Ry/' input.fdf |
| 수정 확인 | diff input.fdf.bak input.fdf |
| 결과 디렉토리 압축 | tar czf results.tar.gz ch01-siesta-scf/ |
| 서버에서 결과 회수 | rsync -avz user@server:~/work/ch01/ ./ch01/ |
| 로그아웃해도 계산 유지 | nohup mpirun -np 4 siesta < input.fdf > siesta.out 2>&1 & |
| 디렉토리 용량 확인 | du -sh */ |
이 표의 명령이 손에 익으면 튜토리얼 본편에서 셸 때문에 막히는 일은 없다. 다음으로 SIESTA란 무엇인가에서 이 튜토리얼의 주력 코드를 개관한다.