이 장의 명령은 모두 노트북에서 실행한다. 원격 쪽 경로는 호스트:경로로 쓰고, 호스트 자리에는 06장에서 만든 별명 vanda를 쓴다. 별명이 없다면 e0123456@vanda.nus.edu.sg:경로로 풀어 쓰면 된다.

scp

scp는 cp의 원격판이다. 형식은 scp 원본 대상이고, 둘 중 한쪽에 호스트가 붙는다.

# 올리기: 노트북 → 클러스터
$ scp h2o.inp h2o.xyz vanda:~/proj/h2o-opt/

# 받기: 클러스터 → 현재 디렉터리(.)
$ scp vanda:~/proj/h2o-opt/h2o.out .

# 디렉터리째 받기
$ scp -r vanda:~/proj/h2o-opt .

원격 경로의 ~는 클러스터의 홈 디렉터리다. 콜론(:)을 빠뜨리면 vanda라는 이름의 로컬 파일로 복사되니 주의한다. 파일 몇 개를 한 번 옮기는 데는 scp로 충분하다.

rsync

rsync는 양쪽을 비교해서 없거나 바뀐 파일만 보낸다. 계산이 돌아가는 동안 출력을 여러 번 받아 볼 때, 전송이 중간에 끊겨 다시 시작할 때 차이가 크다. 대부분의 클러스터에 깔려 있고, macOS와 WSL에도 기본으로 있거나 바로 설치된다.

$ rsync -avhP vanda:~/proj/h2o-opt/ ~/proj/h2o-opt/
옵션뜻
-aarchive. 하위 디렉터리까지, 권한과 수정 시각을 유지하며 복사
-v옮기는 파일 이름을 보여 준다
-h크기를 2.00M처럼 읽기 쉽게
-P진행률 표시, 끊긴 파일은 이어 받기
-n, --dry-run실제로 옮기지 않고 무엇을 옮길지만 보여 준다

같은 명령을 두 번 실행하면 두 번째는 바뀐 것이 없어서 거의 즉시 끝난다.

sending incremental file list

sent 233 bytes  received 14 bytes  494.00 bytes/sec
total size is 600.17K  speedup is 2,429.83

끝의 슬래시

rsync에서 가장 헷갈리는 부분이다. 원본 경로 끝에 /가 있느냐에 따라 결과가 다르다. 아래는 같은 디렉터리를 슬래시 없이, 그리고 슬래시를 붙여 복사한 실제 결과다.

$ rsync -avh proj/h2o-opt a/
sending incremental file list
h2o-opt/
h2o-opt/h2o.gbw
h2o-opt/h2o.inp
h2o-opt/h2o.out
...
$ rsync -avh proj/h2o-opt/ b/
sending incremental file list
h2o.gbw
h2o.inp
h2o.out
...
$ tree a b
a
└── h2o-opt
    ├── h2o.gbw
    ├── h2o.inp
    ...
b
├── h2o.gbw
├── h2o.inp
...

슬래시가 없으면 디렉터리 자체(a/h2o-opt/)가 복사되고, 있으면 디렉터리의 내용물이 대상에 바로 풀린다. 대상 쪽 슬래시는 결과에 영향이 없다. 헷갈리면 양쪽에 슬래시를 붙이고 대상 디렉터리 이름을 원본과 같게 쓰는 습관을 들인다. rsync -avh 원본/ 대상/은 "원본의 내용을 대상에 맞춰라"로 읽힌다.

--delete는 dry-run부터

--delete를 붙이면 원본에 없는 파일을 대상에서 지운다. 슬래시를 잘못 붙인 채 쓰면 엉뚱한 디렉터리가 비워질 수 있다. 쓸 때는 반드시 -n으로 먼저 돌려 목록을 확인한다.

필요한 파일만 받기

계산 디렉터리 여러 개에서 .out과 .xyz만 받고 싶을 때가 많다. --include와 --exclude를 조합한다. 규칙은 앞에서부터 차례로 적용되고, 처음 맞는 규칙이 이긴다.

$ rsync -avh --dry-run --include='*/' --include='*.out' --include='*.xyz' --exclude='*' \
    vanda:~/proj/ ~/proj/
sending incremental file list
created directory /home/kim/proj
./
h2o-opt/
h2o-opt/h2o.out
h2o-opt/h2o.xyz
h2o-opt/h2o_trj.xyz
nh3-opt/
nh3-opt/nh3.out
nh3-opt/nh3.xyz
nh3-opt/nh3_trj.xyz

sent 264 bytes  received 69 bytes  666.00 bytes/sec
total size is 600.17K  speedup is 1,802.31 (DRY RUN)

--include='*/'는 하위 디렉터리 안으로 들어가게 하고, 두 패턴에 맞는 파일은 받고, --exclude='*'가 나머지를 모두 뺀다. 순서를 바꿔 --exclude='*'를 앞에 두면 아무것도 받지 않는다. 패턴은 작은따옴표로 감싸야 셸이 먼저 펼치지 않는다. 목록이 맞으면 --dry-run을 빼고 다시 실행한다.

반대로 큰 파일 몇 종류만 빼고 다 받을 때는 --exclude만 쓴다.

$ rsync -avhP --exclude='*.gbw' --exclude='*.tmp' vanda:~/proj/h2o-opt/ ~/proj/h2o-opt/

무엇을 옮기지 않을까

계산 프로그램은 결과 외에도 큰 중간 파일을 남긴다. ORCA의 .gbw(파동함수)와 .tmp, Quantum ESPRESSO의 outdir 안 파동함수 파일, LAMMPS의 대용량 덤프 파일이 그렇다. 몇 GB씩 되기도 하고, 분석에는 대개 필요 없다. 필요한 것은 보통 출력 텍스트(.out, log.lammps)와 구조(.xyz)다.

옮기기 전에 클러스터에서 크기부터 본다. du -sh는 디렉터리별 용량을 알려 준다.

$ du -sh proj/*
7.0M	proj/h2o-opt
7.0M	proj/nh3-opt

.gbw는 다음 계산의 초기 추정으로 쓸 수 있으니, 받지 않더라도 클러스터에서는 계산이 완전히 끝날 때까지 지우지 않는 편이 안전하다.

작은 파일이 많을 때: tar

파일 수천 개를 하나씩 보내면 파일마다 드는 오버헤드 때문에 느리다. 클러스터에서 tar로 한 파일로 묶고 압축해서 받은 뒤 푼다.

# 클러스터에서: 큰 중간 파일은 빼고 묶기
$ tar czf h2o-opt.tar.gz --exclude='*.gbw' --exclude='*.tmp' h2o-opt
$ tar tzf h2o-opt.tar.gz
h2o-opt/
h2o-opt/h2o_trj.xyz
h2o-opt/h2o.out
h2o-opt/h2o.inp
h2o-opt/h2o.xyz

# 노트북에서: 받고 풀기
$ rsync -avhP vanda:~/proj/h2o-opt.tar.gz .
$ tar xzf h2o-opt.tar.gz

c는 만들기, t는 목록 보기, x는 풀기, z는 gzip 압축, f는 뒤에 파일 이름이 온다는 뜻이다. 풀기 전에 tar tzf로 안을 보면 현재 디렉터리에 파일이 흩어지는 일을 막을 수 있다. 출력 텍스트는 압축이 잘 되는 편이다.

GUI 프로그램

파일을 끌어다 놓는 쪽이 편하다면 SFTP 클라이언트를 쓴다. 모두 ssh 위에서 동작하므로 같은 계정과 키로 접속한다.

프로그램운영체제비고
WinSCPWindowsPuTTY 형식 키(.ppk)로 변환해서 쓰기도 한다
FileZillaWindows, macOS, Linux프로토콜을 SFTP로 고른다
CyberduckWindows, macOS~/.ssh/config의 별명을 읽는다

GUI로는 필터링과 이어 받기가 번거롭다. 계산 디렉터리 여러 개를 정기적으로 받는다면 rsync 명령 한 줄을 스크립트로 저장해 두는 편이 낫다 (셸 스크립팅 가이드).