tar 옵션에 대하여
- tar -C (–directory)
tar 명령은 tar의 실행 위치를 설정하는 -C, --directory <DIR> 옵션을 지원합니다.
이 옵션 뒤에 나오는 path는 해당 directory에서 (cd dirctory) 실행된 것으로 간주됩니다.
command line 옵션 중에서 흔하지 않은 옵션의 위치에 따라 동작이 달라지는 옵션 중 하나입니다.
~/demo $ tree
.
├── a.txt
└── dir
└── b.txt
1 directory, 2 files
~/demo $ tar -czf archive.tgz a.txt --directory dir b.txt
~/demo $ tar -tf archive.tgz
a.txt
b.txt
~/demo $ tar -czf archive2.tgz --directory dir b.txt a.txt
tar: a.txt: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
위의 예시를 보시면, 서로 다른 경로에 있는 a.txt와 b.txt를 동일한 위치에 있는 것처럼 archive file을 만들 수 있습니다.
아래의 예시는 --directory의 옵션에 따라 다르게 동작함을 알 수 있습니다.
- tar 명령은 archiving(
-c)하거나 extracting(-x) 할 때 대상 파일(-f)로 stdin(-)을 지정할 수 있습니다. tar에서 stdin을 -f 로 지정하는 경우는 거의 한가지 유형으로 사용되는데요, stdin과 파이프를 통한 중간 archive file 없이 archive 내용을 전달할 때입니다. 사용 예는 다음과 같습니다:tar -cf - <targets> | tar -xf -
그래서 이걸 어떻게 쓰지 하시는 분도 계실텐데요, 그래서 2가지 예를 가져 왔습니다.
첫번째는 같은 파일시스템에서 구조를 보존하며 내용물을 덮어쓰는 경우입니다.
~/gitclone/dot_files $ tree ~/.vim | head
/home/widehyo/.vim
├── autocmd
│ └── terminal.vim -> ../../gitclone/dot_files/dot_vim/autocmd/terminal.vim
├── bundle
│ └── Vundle.vim
├── cli
│ ├── black.vim -> ../../gitclone/dot_files/dot_vim/cli/black.vim
│ ├── ctags.vim -> ../../gitclone/dot_files/dot_vim/cli/ctags.vim
│ ├── curl.vim -> ../../gitclone/dot_files/dot_vim/cli/curl.vim
│ ├── gnuplot.vim -> ../../gitclone/dot_files/dot_vim/cli/gnuplot.vim
~/gitclone/dot_files $ tar -C dot_vim -cf - . | tar -C ~/.vim -xf -
~/gitclone/dot_files $ tree ~/.vim | head
/home/widehyo/.vim
├── autocmd
│ └── terminal.vim
├── bundle
│ └── Vundle.vim
├── cli
│ ├── black.vim
│ ├── ctags.vim
│ ├── curl.vim
│ ├── gnuplot.vim
사용 예에서 보실 수 있듯이, 보통 cp -r이라는 쉽고 간단한 명령에 의해 대부분 대체될 수 있기 때문에 잘 쓰이지 않습니다.
단, cp -r dot_vim으로 복사하는 경우는 target path에 dot_vim 디렉터리가 복사되는 점(위의 목적에는 .vim으로 복사하기를 원함),
그렇다고 dot_vim에서 cp -r * 으로 target path에 복사하면 *가 hidden file을 제대로 복사하지 못한다는 점에서 tar 를 통한 덮어쓰기가
실제로 cp -r보다 목적에 맞는 드문 경우입니다.
참고로, 위의 동작은 중간에 압축률을 높이는 옵션이 (gzip: -z, zstd: –zstd 등) 순수하게 성능저하만 일으키는 드문 경우이기도 합니다. (archiving / extracting에 드는 cpu resource가 낭비됨)
두번째는 조금 더 실전적인 예인데요, ssh로 접속하는 운영서버의 disk가 거의 차 있어서 중간 archive file을 만드는 것이 불가능한 경우 stdin으로 매개하여 전송하는 예입니다.
~/project $ ssh user@10.51.244.6 tar -C /home/user/project -czf - . | tar -xzf -
~/project $ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
.venv/
no changes added to commit (use "git add" and/or "git commit -a")
~/project $ git diff
diff --git a/hello.py b/hello.py
index e3edb67..fe90c90 100644
--- a/hello.py
+++ b/hello.py
@@ -1,5 +1,5 @@
def hello():
- print("hello in dev")
+ print("hello")
if __name__ == "__main__":
hello()
ssh <user>@<server> [cmd]
ssh 옵션에서 cmd 를 뒤에 붙이면 해당 서버의 유저로 명령을 하나 실행할 수 있는데요, 운영서버의 소스위치를 아는 경우는 일반적입니다.
위에서 소개드린 -C 옵션을 이용해 cd 명령을 생략하여 tar를 ssh가 실행하는 하나의 명령에 넣을 수 있었습니다.
아래 git diff 부분은 운영서버에는 git이 설치되어 있지 않고 개발 서버에만 git이 설치되어 있는 상황을 상정했습니다. 당연하게도, 운영서버에 실제로 돌아가는 코드가 더 중요하기에 개발에 그대로 덮어쓰고, git diff로 무엇이 다른지 확인하는 예시입니다.