Redirection, Pipeline, 그리고 apt-key 학습과 이해.

바로 이전 글에서, 다음 명령에 대해 알아봤었다.

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg && sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/
$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo apt-key add -

이 글에선, 위 명령에서 사용된 Redirection 과 apt-key 명령등을 좀 자세히 알아보려한다.

애당초 첫 명령은 다음을 바꿔쓴 것이다.

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg

curl(또는 wget -qO -)는 모두, 연결한 내용(http 주소등)을 파일로 저장하지 않고 Standard output 으로 넘긴다.

먼저 -q -O(대문자 O 이고, 숫자 0 이 아님) 에 대해 설명한다.

  • q : Quiet. 주절 주절 떠들지(?) 말라는 뜻
  • O : -O file 형식(–output-document=file)으로, 출력을 지정한 파일로 돌리라는 뜻. 생략하면, 원 파일명 그대로 저장한다. 즉, Save As 와 같은 기능이다.

그런데, -O 다음의 – 는 무슨 뜻일까?

“-” 는 바로 stdout 을 뜻한다. (wget 으로 받은 파일을 stdout 으로 보내라는 뜻) 이 Dash 에 관해서는 다음 글이 좋은 참고가 될 듯 하다. (Dash 가 모든 프로그램에서 인식되는 건 아니다.)
제대로, 정확하게 쓰기 위해서는 “-” 대신에 “/dev/stdout”, “/dev/stdin”, “/dev/stderr” 등을 써줘야 한다고 한다.

여기서 | 는 Pipe operator 인데, 앞쪽 명령의 결과를 뒤쪽 명령의 Input 으로 넘기라는 뜻이 된다.


여기서 상상의 날개를 펼쳐보자.

뒤쪽에 있는 gpg 명령을 따로 써보면 (아마도) 이렇게 되지 않을까? (답은 ‘아니오’다.)

gpg --dearmor microsoft.asc > microsoft.gpg

헌데.. 결과로는 microsoft.asc.gpg 와 microsoft.gpg 2개가 생긴다.

$ ll
drwxrwxr-x 1 userxx userxx   98  6월  5 21:18 ./
drwxr-xr-x 1 userxx userxx 1338  6월  5 21:09 ../
-rw-rw-r-- 1 userxx userxx  983 11월 15  2016 microsoft.asc
-rw-rw-r-- 1 userxx userxx  641  6월  5 21:18 microsoft.asc.gpg
-rw-rw-r-- 1 userxx userxx    0  6월  5 21:18 microsoft.gpg

왜??
microsoft.gpg 파일의 크기가 0 임을 염두에 두고, 일단 다음 명령을 먼저 내려보면 해답을 유추해볼 수 있다.

gpg --dearmor microsoft.asc

결과로 microsoft.asc.gpg 파일이 생긴다.
그럼 다음 명령은?

wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor

이 명령은 결과값(.gpg 파일)을 화면(stdout)으로 출력한다. gpg 파일은 텍스트파일이 아니기에 읽어볼 수는 없다. (이상한 글자들이 화면을 채운다.)

자.. 이제 답은 나왔다.

gpg 명령은,

  • 입력을 파일로 받으면, 작업 결과를 ‘입력파일명’에 gpg 를 붙여서 새 파일로 저장한다.
  • 입력을 Standard Input으로 받으면, 결과를 Standard Output, 즉 화면으로 출력한다.

따라서, stdout 을 파일로 저장하려면, Redirection(>)을 사용해서 파일로 출력함을 명시해줘야 한다.

그렇다면 gpg --dearmor microsoft.asc > microsoft.gpg 에서 왜 파일이 2개가 생성되었는지도 알 수 있다.
microsoft.asc.gpg 가 생긴 이유는 위와 같다.
microsoft.gpg 는, 왜 0 인채로 만들어졌을까?
이유는 간단하다.
다음 명령으로 시험해보자.

$ > mm.gpg
$ ll
drwxrwxr-x 1 userxx userxx  110  6월  5 21:35 ./
drwxr-xr-x 1 userxx userxx 1338  6월  5 21:09 ../
-rw-rw-r-- 1 userxx userxx    0  6월  5 21:18 microsoft.gpg
-rw-rw-r-- 1 userxx userxx    0  6월  5 21:35 mm.gpg

앞에 명령이 없는 상태에서 Redirection 을 사용해서 mm.gpg 로 출력을 돌리라고 명령했다.
Input 이 전혀 없었는데도, 출력을 만들라고 하니 그 결과로 mm.gpg 는 크기가 0인, 즉 빈파일로 만들어질 수 밖에 없다.

(** 이게 Bash 와 Zsh 가 좀 다르다. Bash 의 경우 바로 mm.gpg 가 만들어지지만, Zsh 의 경우, 저 명령을 내렸을 때 Std. Input 을 대기하는 상태가 된다.)

gpg --dearmor microsoft.asc > microsoft.gpg 도 마찬가지다.
이 명령은 앞부분 gpg --dearmor microsoft.asc 에서 모든 출력을 끝냈다. 더 넘길 내용이 없다. 그럼에도 불구하고 Redirection 을 했으니 빈 파일이 만들어 질 수 밖에 없다.

이제 이 명령을 완전히 이해할 수 있는 수준이 됐다.

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg

microsoft.asc 파일을 읽어오되, stdout 형태로 gpg 에게 넘기고(gpg 입장에선 stdin), gpg 는 microsoft.asc 를 처리하여, stdout 으로 출력하려 했는데, 그게 Redirection 되었으므로 그 결과 microsoft.gpg 파일이 만들어졌다.


Dash 가 stdout/stdin 을 뜻한다고 했는데..
그렇다면 gpg 쪽에도 stdin 을 명시해줘야 하지 않나?

다시 말하자면, 이렇게?

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor - > microsoft.gpg

물론 이렇게 해줘도 된다.

프로그램에 따라서, – 를 인식하기도 하고, 아예 입력단이 비어있으면 Standard Input 을 기본 입력으로 받게 된다. 어떤 프로그램이 이런 지는 잘 모르겠다.

Pipeline 과 Redirection 에 대한 얘기는 여기서 마무리한다.


이제부터는 데비안/우분투에서 쓰이는 GPG 키 저장방식에 대해 알아본다.

여기서 글머리에 있었던 명령을 다시 옮겨본다.

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg && sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/
$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo apt-key add -

(apt-key add – 에서 – 은, 위에서 설명한 stdin 이다. 즉, gpg 가 처리하여 stdout 으로 넘긴 내용)

첫번째 명령은 microsoft.asc 파일을 stdout 으로 넘기고, gpg 가 그것을 받아 결과를 microsoft.gpg 라는 파일로 저장한다. 그리고 그 파일을 /etc/apt/trusted.gpg.d/ 로 옮긴다.

두번째 명령은, gpg 가 결과를 파일로 저장하지 않고, stdout 으로 넘기는데, 또 다시 pipeline 을 사용하여 apt-key 로 건네준다.

이 부분 처리가 확연히 다르다. 하나는 파일로 만든 뒤 그 파일을 해당 위치로 옮기고, 또 하나는 stdout/in 을 사용해서 apt-key 로 처리한다.

어떻게 다를까?
우분투에서 gpg 키는 /etc/apt/trusted.gpg 파일에 저장한다. gpg 파일이 추가되면, 이 파일에 덧붙여지면서 키가 추가된다.
저장소(Repository) 추가도 마찬가지다. /etc/apt/sources.list 에 저장소 위치가 추가된다.

그런데, 위 방식은 다소 예전 방식이다.
최근엔 위 방식에 더하여, 각자 파일들을 별도 디렉토리에 두는 방식이 선호되고 있다.
즉,

/etc/apt/trusted.gpg.d/
/etc/apt/sources.list.d/

이런 디렉토리에 각각 *.gpg 파일과 *.list 파일을 저장하여 관리하는 방식이 최근 방식이다.
이 방식의 장점은, 설치/삭제가 쉽다는데 있다.

어떤 방식을 써도 결과는 같다.

추가된 저장소를 삭제하려면 sources.list 를 직접 편집하면 되므로 크게 어려울 건 없지만, trusted.gpg 에 추가된 키는 전용 프로그램을 써야만 삭제(추가도 마찬가지)가 가능하다.
그 프로그램이 바로 apt-key 이다.

사용법:

  • 키 나열 : apt-key list (trusted.gpg 와 trusted.gpg.d 내용이 구분되어 출력된다.)
  • 키 추가 : apt-key add xxx.gpg
  • 키 삭제 : apt-key del 키값(list 로 나온 키값중 끝에서 8문자)

따라서, 위에서처럼 이렇게 명령을 내리면,

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo apt-key add -

wget 으로 받아온 asc 파일은 stdout/stdin 으로 넘겨져서 gpg 가 작업을 하고, 역시 다시 stdout/stdin 으로 apt-key 로 넘겨진 후, 마지막으로 /etc/apt/trusted.gpg 에 추가된다.

추가된 키를 지우고 싶다면, 일단 apt-key list 로 키를 확인한다.
VS code 의 키는 다음과 같다.

pub   rsa2048 2015-10-28 [SC]
      BC52 8686 B50D 79E3 39D3  721C EB3E 94AD BE12 29CF
uid           [ unknown] Microsoft (Release signing) <gpgsecurity@microsoft.com></gpgsecurity@microsoft.com>

여기서 필요한 값은 마지막 8문자, BE1229CF 이다.
마지막 8자에 대한 내용은 다음 글에서 알 수 있었다.

Ask Ubuntu: How can I remove gpg key that I added using apt-key add -?

따라서, 이런 명령으로 키를 지울 수 있다.

sudo apt-key del BE1229CF

아니면 키 전체를 입력해도 된다.

sudo apt-key del "BC52 8686 B50D 79E3 39D3  721C EB3E 94AD BE12 29CF"

혹시라도 키값(끝 8자)이 중복될 수도 있으므로, 이렇게 하는 편이 더 안전할 지도 모르겠다.


apt-key 로 작업을 하면 trusted.gpg 에 키가 추가/삭제가 된다.

다음 명령은, 키를 trusted.gpg.d 디렉토리에 키를 저장한다.

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg && sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/

이 글 내내 mv 를 사용했는데, mv 를 하게 되면 microsoft.gpg 파일의 소유권이 root 가 아니고, 명령을 실행한 사용자가 된다. 따라서 조금 애매해 질 수도 있다.

따라서, 다음 명령이 좀 더 정확하다. (설명은 또 다른 글에서)

$ wget -qO - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null

키를 지우고 싶다면, 그냥 저 파일을 지워버리면 그만이다. apt-key 로 확인을 할 수는 있겠지만, 굳이 apt-key 로 지울 필요는 없다.
만약, trusted.gpg.d 디렉토리에 있는 키파일을 apt-key 로 삭제하면, apt-key 는 키를 삭제한 후 백업파일(xxx.gpg~)을 생성해놓는다. 다시 추가하고 싶다면 파일명만 바꿔주면(즉, 뒤의 ~ 만 떼어버린다) 된다.

또 한가지. 이전 글에도 쓴 내용이지만, gpg 파일 소유권 문제를 생각은 해봐야 한다.
이렇게 생성된 gpg 키는 사용자에 소유권이 있고, 권한도 rw-rw-r–(0664)가 된다. 보통 gpg 파일은 add-apt-repository 등으로 생성했을 때 소유자는 root, 권한은 0644 가 된다. 이게 무슨 문제가 될 지는 모르겠다.

어떤 방법을 통하든, 결과는 같다.
그저 지금까지, 다른 글에서 시키는 대로 무작정 따라만 했었지만, 이제는 왜 그런지 이해를 할 수 있게 됐다는 점이 다를 뿐.

안녕하세요. 글 남겨주셔서 고맙습니다.