Homebrew Cask로 설치된 앱들이 자체 업그레이드 되었다면 어떻게 될까?
과거 Homebrew로 패키지를 관리하다 보니 가끔 데스크톱 GUI 앱들도 이걸로 관리하면 어떨까 하는 생각이 있던 적이 있었다. 그런데 놀랍게도 당시 Cask라는 것도 존재해서 바로 이걸로 데스크톱용 앱들도 설치하고 업그레이드를 할 수 있었다. 그저 개인의 취향이긴 했지만 당시에는 정말 마음에 드는 환경이었다.
그런데 가만 생각해 보니 뭔가 큰 결함(?) 같은 게 하나 있었다. 설치된 GUI 앱들이 워낙 유명해서(?) 자체 업그레이드 기능을 가지고 있었던 것이었다. 그래서 이런 앱들을 자주 쓰게 되면 어쩔 수 없이 앱들이 알아서 업그레이드가 되어버릴 테고 이는 Homebrew가 관리하고 있던 체계에 영향을 줄 수밖에 없을 거다. Homebrew는 아직 구 버전이 설치되어 있는데 실제론 최신 버전이 설치되어 있을 테니 말이다.
실제로 최근 Homebrew의 upgrade 커맨드를 쓰다 보면 아래와 같은 메시지를 볼 수 있었다.
Warning: The cask 'docker-desktop' cannot be upgraded as-is. To fix this, run:
brew reinstall --cask --force docker-desktop
Warning: The cask 'google-chrome' cannot be upgraded as-is. To fix this, run:
brew reinstall --cask --force google-chrome
Warning: The cask 'visual-studio-code' cannot be upgraded as-is. To fix this, run:
brew reinstall --cask --force visual-studio-code
이 메시지들은 Homebrew Cask로 설치된 앱들을 업그레이드할 수가 없으니 강제로 설치하라는 그런 의미다. 이는 아마도 자체 업그레이드 기능과 관련이 있다고 밖에 생각할 수 없는 경고다.
내용이나 중요도가 어떻든 콘솔 메시지에 이런 게 찍혀 나오는 건 좀 불쾌한 일이다. 적어도 내 관리 능력에 의문을 제기하는 것일 테니 말이다. 지금에 와서 생각해 보면 Homebrew로 데스크톱 GUI 앱들을 관리할 의미는 별로 없었고 오히려 이런 불편함만 남긴다고 생각되었다.
그래서 이 자체 업그레이드된 앱들과 Homebrew Cask와의 연결고리를 끊어주고 싶었다. 이와 관련된 방법을 찾아보니 대충 두 가지 방법이 나왔다. 물론 이를 실제로 행하는 것은 순탄치만은 않았기에 이런 글을 남겨본다.
주의: 이 글은 팁이라기보다는 일기에 가까운 글임에 주의하자.
대충 인연만 끊어주기
가장 간단해 보이는 방법은 핀을 박아버리는 거다. 제목처럼 대충 인연만 끊어주는 기능으로 핀을 박아버리면 업그레이드 대상에서 제외시켜 준다.
사용법도 간단했다. pin 명령으로 특정 앱의 핀을 박을 수 있고, 반대로 unpin 명령으로 다시 핀을 뽑아줄 수 있다.
그래서 실제로 시험해 봤다.
$ brew pin docker-desktop google-chrome visual-studio-code
Error: docker-desktop not installed
Warning: google-chrome has `auto_updates true` and may update itself outside Homebrew despite being pinned.
Warning: visual-studio-code has `auto_updates true` and may update itself outside Homebrew despite being pinned.
잘 된 것 가... 어...
아니 docker-desktop은 왜 에러가 날까? 모르겠지만 일단 지금은 넘어가자.
어쨌든 이렇게 핀을 박아두면 이제 upgrade 때마다 위의 불쾌한 경고 메시지는 보이지 않는다.
그런데 대신 다른 메시지가 보였다.
$ brew upgrade
....
==> 2 Pinned casks
google-chrome 73.0.3683.103
visual-studio-code 1.41.1
...
보다시피 핀이 박혀 있어서 업그레이드를 안 한다는 메시지다.
아니 이러면 과연 이게 해결된 것일까? 그저 경고 메시지가 뜨는 게 싫어서 한 행동인데 이 메시지 내용만 바뀌는 거면... 아무 의미가 없을지도 모르겠다. 나는 도대체 뭔 짓을 한 것일까.
다른 방법을 써볼까? 위에서 언급한 것 외의 다른 방법으로는 그냥 삭제해 버리는 방법이 있다고 한다.
brew uninstall --cask CASK_NAME
그냥 삭제하는 방법이다. 하지만 굳이 써보지는 않았다. 왜냐하면 삭제할 때 잘 대응해야 한다고 설명에 적혀있어서다. 낡고 늙은 개발자에게 귀찮은 건 너무 질색이다.
그렇다면 결국 유일했던 방법은 핀을 박는 것이었던 듯하다. 그런데 앞서 언급했다시피 이렇게 핀을 박는 게 과연 좋은 방법인가는 잘 모르겠다. 하지만 적어도 Homebrew Cask가 버전 관리를 못 해서 조마조마해하는 건 안 볼 수도 있는 것 같다.
그런데 docker-desktop은 왜 저래?
아까 넘어갔던 녀석을 다시 봐야겠다. 해당 부분만 정리하면 이런 모습이었다.
$ brew pin docker-desktop
Error: docker-desktop not installed
설치가 안 되어 있었다고? 아니 그럼 그전에 왜 경고하면서 강제로 새로 설치하라고 난리였던 걸까? 이상한 녀석이다.
사실은 upgrade 도중의 메시지를 놓쳐버렸기에 잘 모르고 있었는데 이 녀석은 정말 설치한 적이 없었다.
==> Migrating cask docker to docker-desktop
Error: inreplace failed
/usr/local/Caskroom/docker-desktop/.metadata/2.0.0.3-ce-mac81,31259/20190420162832.043/Casks/docker-desktop.rb:
expected replacement of /\A\s*cask\s+"docker"/ with "cask \"docker-desktop\""
그러니까 기존에 Cask로 설치된 것은 docker라는 앱이었었는데 이게 docker-desktop으로 바뀌면서 마이그레이션이 진행되었어야 했는데 알 수 없는 이유로 마이그레이션이 안 되고 있었다는 말이다.
어떻게 지우면 좋을까 생각해 봤는데 사실 그다지 좋은 답은 없었다. 애초에 관리 영역에서 벗어나 버린 녀석이라 Cask로 삭제하는 방법도 쓸 수가 없었다.
그래서 될 대로 되라며 그냥 지워버렸다. 뒷감당은 나중에 하지 뭐.
$ rm -rf /usr/local/Caskroom/docker
$ brew cleanup
$ brew upgrade
다행히도 별 뒷감당은 없어도 되나 싶었다. 단지 upgrade 과정에서 여전히 마이그레이션을 진행해 주지는 않았다.
너무 귀찮았지만 삽을 뽑았으니 삽질 흉내라도 내봐야겠다. 그래서 따로 설치해 봤다.
$ brew install --cask docker-desktop
이제 해결될 것ㅇ...
Homebrew Cask가 좀 귀찮게 하는 점이 있다면 이걸로 설치될 파일이 이미 저장공간에 위치하고 있다면 오류를 내면서 설치를 중단한다는 점이 있다.
이번에는 Applications 폴더에 Docker.app이라는 파일이 남아있다며 설치가 중단되었다. 처음에는 좀 당황했지만 이미 삽질을 시작한 거 대충 하자며 언급된 파일을 그냥 삭제해 버렸다.
그리고 다시 설치를 시도했다.
$ brew install --cask docker-desktop
...
Error: It seems there is already a Binary at '/usr/local/bin/docker-credential-desktop'.
또 시작이다. 잔재가 여기저기 흩어져 있었나 보다. 어쩔 수 없이 수동으로 또 삭제했다.
귀찮음이 폭발하기 직전이다. 이제 제발 해결되어 줘.
$ rm /usr/local/bin/docker-credential-desktop
$ brew install --cask docker-desktop
...
Error: It seems there is already a Binary at '/usr/local/bin/docker-credential-ecr-login'.
ㅋㅋㅋ 젠장. 폭발한다. 콰쾅.
이 뒤의 대응의 상세한 내용은 생략한다. 왜냐하면 위처럼 특정 파일이 이미 존재한다며 설치가 중단되면 해당 파일을 수동으로 삭제하고 다시 설치를 시도하는 일의 반복이었기 때문이다. 아예 짜증 나서 /usr/local/bin 디렉터리에서 docker로 시작되는 모든 파일을 와일드카드로 삭제해버리기까지 했다.
이런 간단하지만 귀찮음이 치열했던 사투 끝에 결국은 끝을 봤다.
$ brew install --cask docker-desktop
...
🍺 docker-desktop was successfully installed!
참 먼 길을 기어 왔다.
문제를 처리했는데 왜 보람이 안 느껴질까
나는 왜 이 짓을 했던가.
사실 도커는 당분간 쓸 일이 없다. 굳이 이런 지랄을 떨 필요가 없었다. 그런데 도대체 왜 그랬던 걸까? 지금 생각해 보니 참 이해가 안 된다.
아마도 자주 쓰는 커맨드에 경고 메시지가 뜨는 게 싫었었나 보다. 손에만 결벽증이 있는 게 아니라 콘솔 메시지에서도 결벽증이 생긴 모양이다.
...
먼 산이 참 푸르다. 눈을 쉬게 하는데 딱 좋을 것 같다. 잠깐 외면 좀 하고 와야겠다.