머신러닝과 같이 큰 데이터를 다루는 일을 하다 보면 한 컴퓨터에서 다른 컴퓨터로 큰 파일을 옮겨야 하는 경우들이 자주 있습니다. 예를 들어 코딩은 내 컴퓨터에서 하고, 모델링을 하기 위해서 코퍼스를 서버로 옮기는 경우가 있겠죠. 외장하드를 이용할 수도 있고, USB 드라이브를 이용할 수도 있고, 플로피... 테이프... 아무튼 여러가지 방법이 있습니다.
1. 묶어서 scp
이때 가장 많이 쓰는 방법 중 하나가 scp를 이용하는 것입니다. 대부분 서버에 ssh 서버가 설치되어있기 때문에 아주 간편하게 파일들을 복사할 수 있습니다. corpus라는 디텍토리가 있고 이 것을 서버로 통째로 보내고 싶다고 가정해보겠습니다.
$ tar -cf corpus.tar corpus
$ scp corpus.tar ceongjeein@192.168.86.36:/home/ceongjeein/Workspace/
(서버에서)
$ tar -xf corpus.tar
보통 이런 식으로 옮길 데이터를 tar로 묶고, scp를 이용해서 서버로 옮긴 다음에, 서버에서 tar를 풀어줍니다.
2. 파이프를 이용해서 한 번에!
첫번째 방법은 직관적이기는 하지만 임시로 쓸 tar 파일을 만들고 서버에서 또 풀어야 한다는 단점이 있습니다. 이를 해결하기 위해서 아래처럼 할 수 있습니다.
$ tar -cf - corpus | ssh ceongjeein@192.168.86.36 'cat - | tar -xf - -C /home/ceongjeein/Workspace'
- tar 파일을 만들 때 -f의 인자로 실제 파일 이름 대신 -를 주면 표준출력으로 결과를 보냅니다.
- 이 결과를 파이프를 통해서 ssh로 보내구요.
- ssh 마지막 인자를 통해서 서버의 명령을 원격으로 실행시킬 수 있습니다.
이 경우에는 서버에서 'cat -xf - -C /home/ceongjeein/Workspace'를 실행시키는 것이고요. - cat은 인자가 - 이면 표준 입력으로 받은 내용을 그대로 다시 표준 출력으로 보냅니다.
- tar는 파일을 만들 때와 마찬가지로 -f의 인자가 - 이면 실제 파일 대신 표준입력으로 데이터를 읽습니다.
이 경우에는 ssh를 통해서 넘어오고 있는 corpus 묶음입니다.
-C 옵션은 tar의 내용물을 풀 디렉터리입니다.
이렇게 한 줄이면 중간 tar 파일을 만들 필요가 없이 현재 내 컴퓨터의 디렉터리를 통째로 서버로 보낼 수 있습니다. 타이핑이 좀 필요하긴 하지만, 익숙해지면 더 편하고 무엇보다 폼(?)이 나기도 합니다.
그러나 문제가 하나 있습니다. 바로 두 방법 모두 SSH를 통해 파일을 복사하기 때문에 필연적으로 오버헤드가 발생하고 파일 전송 속도가 느려진다는 점입니다. (다른 주제지만 SSH는 보안을 위해서 인증, 암호화/복호화 등의 작업을 동반합니다).
제가 테스트 삼아 만든 저 corpus 디렉터리는 약 4.7GB인데 LAN 상의 머신 사이에 옮길 경우 두 방법 모두 약 3분 정도가 걸립니다. 초당 26MB의 속도가 나오는 셈이죠. 빨리 데이터를 서버에 올려서 나의 엄청난 새로운 아이디어를 돌려보고 싶을 때는 정말 속 터지는 순간이죠. 물론 데이터 올리고 있다는 핑계로 잠시 바람을 쐬러 가기에는 참 좋은 이유이기도 합니다. (옛날에 컴파일 한번 걸어두고 나가서 한 바퀴 산책하고 오던 때가 생각하는군요.)
3. nc를 이용해서 빠르게 복사하기
보안을 생각한다면 SSH가 참 좋은 방법입니다. 하지만 나는 보안보다 파일을 빠르게 옮기고 싶다는 분들은 다른 방법이 있습니다. 바로 nc라는 명령을 사용하는 것입니다. (Mac에서는 homebrew를 사용해서 brew install netcat으로 설치하시면 됩니다.)
nc는 여러 가지 기능이 있는데 그중 하나가 TCP 연결을 통해서 바로 데이터를 주고받을 수 있는 기능입니다. nc는 이런저런 오버헤드를 최대한 배제하고 통신에만 집중합니다. 물론 더 빠르겠죠?
먼저 서버에 접속해서 아래와 같이 nc를 서버 모드로 실행시킵니다.
$ nc -l 1234 | tar -xf -
-l 뒤에 숫자는 nc가 연결을 기다릴 포트입니다. 이렇게 nc를 띄워두면 데이터가 들어오는 순간 파이프를 통해 tar로 보내게 되고, tar는 표준 입력으로 들어오는 데이터를 현재 디텍토리에 풀기 시작합니다. (tar의 -가 뭔지 궁금하신 분들은 위 두 번째 방법에 설명이 있습니다)
이 상태에서 보낼 데이터가 있는 내 컴퓨터에서 아래 명령을 실행합니다.
$ tar -cf - corpus | nc 192.168.86.36 1234
tar가 corpus 디렉터리를 묶어서 표준 출력으로 보내고, nc는 이를 받아서 192.168.86.36 서버의 1234 포트로 데이터를 보냅니다. 이 명령이 완료되고 나서 서버쪽 콘솔을 보시면 파일들이 디렉토리 채로 고스란히 올라와있는 것을 볼 수 있습니다.
똑같은 디렉토리를 이 명령으로 보내보았는데 약 45초가 걸렸습니다. 초당 104MB의 속도가 나온 셈이죠. 제 환경이 1 Gbps 망인데 거의 네트워크 대역폭을 다 쓴 셈입니다. SSH를 통하는 방법보다 무려 4배가 빠릅니다. (그리고 쉴 시간도 4배가 줄었습니다.)
4. 마무리
앞에도 언급했지만 SSH 대비 nc의 단점이 있습니다.
- 서버에 먼저 접속에서 nc를 서버 모드로 실행시키야 합니다.
- SSH와 다르게 종단 간 암호화가 되지 않기 때문에 누가 중간에서 나의 소중한 데이터를 훔쳐볼 수도 있습니다.
하지만 많은 경우 이 두 가지 단점을 상쇄시킬 정도로 nc의 매력이 있습니다. 필요에 맞는 좋은 도구를 선택하셔서 마음의 안정, 쉬는 시간 모두 얻으시길 바랍니다.
'Linux' 카테고리의 다른 글
디렉터리 구조를 확인하고 싶을 때 - tree (0) | 2020.05.23 |
---|---|
직전 명령의 마지막 인자 재활용하기 : !$ (0) | 2020.05.06 |
내 컴퓨터와 서버 디렉터리 동기화 - rsync (0) | 2020.05.02 |
특정 포트를 잡고 있는 프로세스 알아내기 (0) | 2020.04.29 |
텍스트 파일의 특정 줄 주변을 보고 싶을 때 : head & tail (0) | 2020.04.28 |