2P by GN⁺ | ★ favorite | 댓글 2개
  • Unix 사용자가 ~/bin/에 개인 스크립트를 넣어 PATH에 추가하면, 짧은 명령 이름이 새 시스템 명령과 충돌할 수 있음
  • Debian/Ubuntu처럼 제공 명령이 많은 환경에서는 위험이 더 커지며, 예시 Ubuntu 노트북의 /usr/bin 명령은 21,733개로 집계됨
  • 개인 명령 앞에 쉼표(,) 를 붙이면 셸과 도구가 일반 파일명 문자로 처리하면서도 시스템 명령과 쉽게 구분됨
  • 쉼표는 Shift 없이 입력할 수 있고, 셸에서 의미가 강한 괄호·백슬래시·콜론·백틱·작은따옴표·슬래시·점보다 충돌 여지가 적음
  • , 뒤에 Tab을 누르면 개인 명령 목록을 바로 훑을 수 있어, ~/bin/ 명령 이름을 깔끔하게 유지하기 쉬움

개인 명령 이름이 충돌하는 이유

  • 많은 Unix 사용자는 홈 디렉터리에 ~/bin/을 만들고 PATH에 추가해 개인 편의 명령과 셸 스크립트를 사용함
  • 문제는 개인 스크립트 이름이 보통 짧은 소문자 조합이라 기본 시스템 명령과 닮기 쉽다는 점임
  • Linux 배포판이 새 명령을 추가하면, 기존 개인 명령과 이름이 우연히 같아질 수 있음
  • Debian 계열 환경에서는 제공 명령 수가 많아 이 문제가 더 현실적으로 다가옴
    • 예시 Ubuntu 노트북에서 /usr/bin 바로 아래 명령 수를 세면 21,733개가 나옴
    • apt-file search -x '^/usr/bin/[^/]*$' | wc -l

쉼표 접두사가 주는 이점

  • 해결책은 개인 명령 이름을 입력하기 쉬우면서도 시스템 명령 이름으로 잘 선택되지 않을 형태로 바꾸는 것임
  • 입력 편의성의 기준은 Shift 키를 쓰지 않는 것이며, 이 조건을 만족하면서 안전한 문자는 많지 않음
    • 소문자는 이미 시스템 명령에 흔히 쓰임
    • 괄호, 백슬래시, 콜론, 백틱, 작은따옴표는 셸에서 특별한 의미를 가짐
    • 슬래시는 디렉터리 구분자라 파일명에 들어갈 수 없음
    • 점은 파일명 맨 앞에서 숨김 파일을 뜻하고, 다른 위치에서도 확장자 구분에 자주 쓰임
  • 남는 선택지는 단순한 쉼표(,) 이며, 주변 도구와 셸은 쉼표를 파일명 안의 일반 문자로 처리함
  • 개인 명령마다 쉼표를 접두사로 붙이면 시스템 명령과 명확히 구분되어 이름 충돌을 피하기 쉬움
  • Tab 완성과 함께 쓰면 ,를 입력한 뒤 개인 명령 목록을 바로 확인할 수 있음
    • 예시 목록에는 ,complete-scp, ,complete-ssh, ,coreoff, ,coreon, ,find, ,go-thpgp, ,gr, ,hss, ,mount-thpgp, ,mount-twt, ,range, ,svn-store-password, ,umount 등이 포함됨
  • 이 방식은 약 10년 동안 사용되어 왔고, 개인 ~/bin/ 명령 이름을 깨끗하게 정돈하는 방법으로 권장됨

댓글과 토론

Hacker News 의견들
  • 제목만 봤을 때는 끔찍한 아이디어일 줄 알았는데, 실제로는 꽤 마음에 듦. 특히 탭으로 내 도구들을 전부 나열하는 부분이 좋았음
    최근에는 네임스페이스 충돌을 많이 겪지는 않았고, 관리직으로 옮긴 뒤 기술 감각이 좀 느슨해진 것도 사실임. 내 기술 스택이 10년쯤 낡은 느낌인데, 다시 최신 감각을 따라잡으려면 어디서부터 시작하면 좋을지 궁금함

    • 요즘 멋진 방식은 여가 시간에 직접 뭔가를 만들고, 만드는 과정에서 자연스럽게 배우는 것 같음. 자급자족, 창의성, 스스로 시작하는 태도가 요즘의 감각이고, 많이 만들수록 실제 문제를 해결하는 요령과 최신식 해법을 스스로 찾아낼 동기가 생김
    • 나도 관리 쪽에 있고, 계속 따라가지 않으면 기술이 퇴화할 것 같다고 느낌
      내가 하는 방식은 내 삶을 편하게 만드는 도구를 직접 만드는 것임. 예를 들어 회사에서 단순 조회에 자주 쓰는 웹 서비스가 있으면 API가 있는지 찾아보고, 일상 작업을 빠르게 하려고 CLI를 작성함. 마음에 들게 다듬은 뒤 팀에 공유하지만, 다른 사람들을 설득해 써보게 하는 건 어렵더라. 그래도 매일 내가 쓰기 때문에 크게 신경 쓰지는 않음
    • 같은 이유로 업무에서 익숙한 스택이 아니라 더 유행하는 별도 스택으로 사이드 프로젝트를 만들었음
      새로운 관점을 보고 트렌드에 대해 대화할 수 있으려는 목적이었고, 그중 일부는 이제 업무에도 넘어왔음. 덕분에 오래된 구성요소들에 대해서도 더 깊이 이해하게 됨
  • 이 문제가 잘 이해되지는 않음. 내 bin 디렉터리를 $PATH의 끝이 아니라 앞에 두면 됨. 내 명령을 둘러보려면 그냥 ls ~/bin을 실행함

    • 그러다 어떤 도구가 $0이 시스템 경로에 있다고 기대하는데, 그게 깨지면서 답답한 디버깅이 시작될 수 있음
      결국 어느 쪽 독을 고르느냐의 문제임
    • 그냥 내가 붙인 이름을 기억하면 되지 않나? 이게 왜 일종의 해킹처럼 여겨지는지 모르겠음
    • 장점 중 하나는 fzf 자동완성을 쓸 수 있다는 것임. 예를 들어 fish에서는 명령의 첫 글자를 치고 Tab을 눌러 fzf를 띄울 수 있음
      그러면 ,+Tab만으로 사용자 정의 명령을 빠르게 걸러낼 수 있음. 반면 ls ~/bin은 자주 하는 작업치고는 입력할 글자가 많고, 아니면 ls+위쪽 화살표 여러 번으로 먼저 자동완성을 찾아야 할 수도 있음
    • ls ~/bin,보다 입력이 훨씬 느림
  • 나는 git을 얇게 감싼 래퍼에 aa, st, di, dp, cm, le 같은 짧은 사용자 정의 명령 이름을 씀
    이 중 하나는 어떤 시스템에 기본 설치되는 유틸리티와 실제로 충돌함. 그래도 내 bin 디렉터리가 시스템 디렉터리보다 $PATH 앞에 있어서 내 것이 이기고, 충돌하는 그 도구에는 별 관심이 없음. 나한테 유용한 다른 도구가 내 도구와 충돌한다면, 내 도구 이름을 바꾸기보다는 그 다른 도구에 충돌하지 않는 별칭을 붙일 가능성이 큼. 이 두 글자 도구들이 너무 편함

    • 이런 방식은 apt-get upgradeDwarf Fortress를 실행하는 식의 문제로 이어질 수 있음
      https://askubuntu.com/questions/938606/dwarf-fortress-starti...
    • 맞음. 1~3글자 이름은 사용자 별칭, 함수, 스크립트와 표준 유틸리티를 위해 남겨둬야 함
    • git 별칭은 대체로 g로 시작하는 두 글자 조합으로 만듦. 예를 들어 gsgit status
      그런데 가끔은 진짜로 GhostScript가 필요할 때가 있음. PDF 파일에 글꼴을 임베드할 때 같은 경우에 아주 훌륭함. 보통 그럴 때는 env gs를 씀
    • 내 개인 명령은 전부 j로 시작함. java가 등장했을 때 꽤 재미있어졌음. 쉼표를 쓰는 건 꽤 흥미로운 아이디어임
      그래도 k로 시작하지 않은 건 다행임, KDE 때문에 :)
    • 다소 강한 생각이지만, 시스템 명령은 사용자 명령만큼 쉽게 접근 가능하면 안 된다고 봄. 어떤 형태로든 네임스페이스가 있어야 함
      예를 들어 mkfssys::mkfs 같은 식으로 호출해야 한다고 생각함. 시스템 명령과 사용자 명령을 가르는 선은 여러 방식으로 정의될 수 있고, 애매한 부분도 있겠지만, 사용자가 왜 있는지도 모르고 명시적으로 설치한 적도 없는 명령을 실수로 실행할 수 있다면 그건 전역 네임스페이스에 바로 노출되면 안 되는 명령임
  • 관련된 질문이 있음
    나는 대부분 Windows를 쓰고, 글쓴이처럼 Python 중심의 CLI 스크립트를 여러 개 만들어 ~/bin/에 해당하는 곳에 둠. python.exe.py 확장자의 기본 프로그램으로 설정하고 .py%pathext%에 추가하면, 어느 경로에서든 hello만 입력해 ~/bin/hello.py를 실행할 수 있고 하루에도 수백 번 씀. 요즘 Linux를 더 많이 쓰고 있지만 아직 초보라서 같은 식으로 만들지 못했음. Linux에는 “연결된 프로그램” 개념이 없는 것 같아서 .py 파일을 그냥 호출하고 셸이 Python으로 실행하게 할 수 없음. 물론 스크립트에 chmod +x를 줄 수 있지만, 그러면 스크립트 자체에 셔뱅을 넣어야 해서 하드코딩처럼 느껴져 불편함. 나중에 .py 스크립트를 /usr/bin/python이 아니라 /usr/bin/nohtyp로 실행하고 싶어지면 어떡하나 싶음. 게다가 스크립트를 호출할 때 .py 부분을 생략하는 방법도 못 찾았음. Linux 설계를 비판하려는 건 아니고 장점이 많다는 건 알지만, 정말로 $PATH에 있는 hello.pyhello로 실행하고 싶음

    • Linux에서는 여전히 셔뱅이 이 문제에 맞는 도구라고 봄. 가볍게 가려면 경로 안에 my_python 심볼릭 링크를 두고, 셔뱅을 /usr/bin/env my_python으로 쓰면 됨
      더 원칙적인 접근을 원하면 update-alternatives 도구를 보면 됨. 이런 추상화를 더 일반적으로 제공함: https://linuxconfig.org/how-to-set-default-programs-using-up...
    • 해결 방법은 다른 사람들이 이미 말했지만, 왜 그런지 한 가지 덧붙이고 싶음
      Linux에서는, 사실 Windows 외 대부분의 플랫폼에서는 파일 확장자의 의미가 훨씬 약함. 어떤 종류의 실행 파일이든 확장자가 아니라 +x 플래그 등으로 실행 가능 여부가 정해짐. 덕분에 구현 언어를 바꿔도 호출 쪽을 깨지 않고 다시 작성할 수 있음. .py 확장자는 가져와서 쓰는 모듈에나 의미가 있고, 실행되는 스크립트라면 필요할 때 셔뱅을 보면 됨. 외부 배포 스크립트는 보통 #!/usr/bin/env python을 쓰고, 배포판 패키지에 포함된 스크립트는 #!/usr/bin/python 등으로 덮어써짐. 또 셔뱅은 여러 인자를 지원하지 않지만 GNU env는 이를 흉내 낼 수 있는 -S 인자를 지원함. 다만 인자 길이 문제는 남음
    • 파일 이름에서 그냥 .py를 빼면 됨. "hello"라고 부르는 건 완전히 괜찮음
      셔뱅의 단점은 잘 떠오르지 않음. 정말 다른 인터프리터로 실행하고 싶다면 "nohtyp hello"처럼 명시하면 됨. 그래도 너무 거슬린다면 셸 시작 파일에 별칭을 정의할 수 있음. 예를 들어 bash에서는 alias hello="python3 /path/to/hello.py"처럼 할 수 있음. 마음만 먹으면 지정한 디렉터리의 내용에 대해 이런 별칭을 자동으로 만드는 짧은 스크립트도 쓸 수 있음
    • 그런 개념이 있긴 하지만 셸 문법 안에 있지는 않음. 보통 데스크톱/GUI에 위임되는 애플리케이션 차원의 문제
      셸 스크립트에서는 보통 셔뱅을 추가하고 파일을 실행 가능하게 만들어, 실행 파일을 스크립트 자체에서 선언함. 셔뱅을 일종의 파일 확장자처럼 생각하면 됨. chmod +x ./malware.py./malware.py가 동작하지 않으면 셔뱅이 가리키는 경로를 확인하면 됨. 인터프리터가 스크립트를 일반 인자로 실행할 수 있다면 xdg-open malware.py 같은 방식으로도 비슷한 동작을 만들 수는 있음. 기본 파일 관리자에서 더블클릭하는 것과 같을 것임. Linux를 주 데스크톱 운영체제로 쓸 때 xop라는 별칭을 둔 적이 있지만, 이미 기본 동작이 맞는 이미지나 문서 같은 데이터 파일에만 썼음. 실행 가능한 스크립트의 기본 프로그램을 인터프리터로 설정하는 건 추천하지 않음. 기본적으로 스크립트를 실행하지 않고 편집기에서 열고 싶을 수도 있음. xdg-open은 Gnome 쪽 도구라고 생각하지만 다른 데스크톱에서도 쓸 수 없다는 뜻은 아니고, Xubuntu에서도 썼음. 정말로 모든 Python 파일을 GUI 문맥에서도 기본 실행하고 싶다면 그런 기본값을 설정할 수는 있겠지만, man xdg-open이 도움이 될 수 있음. 다시 말하지만 좋은 조언은 아님
    • 목표를 직접 달성해주지는 않지만, 셔뱅은 반쯤만 하드코딩임. 셔뱅을 쓰는 “올바른” 방식은, 몇 가지 주의점은 https://unix.stackexchange.com/a/29620을 보더라도, #!/usr/bin/env python
      이렇게 하면 경로에서 처음 발견되는 python이 실행됨. 나중에 /usr/bin/python이 아니라 /usr/bin/nohtyp로 실행하고 싶다면, /usr/bin보다 먼저 검색되는 디렉터리에 /usr/bin/nohtyp를 가리키는 python 심볼릭 링크를 만들 수 있음. 예를 들어 ~/myCommandPreferences$PATH 앞에 추가하면 됨
  • $PATH 충돌을 피하는 다른 방법은, 다른 실행 파일이 쓸 가능성이 낮은 아주 긴 실행 파일 이름을 만들고 bashrc에 짧은 별칭을 두는 것임
    별칭은 스크립트 내부에서 호출되는 실행 파일에는 영향을 주지 않고, 내 스크립트에서는 긴 이름으로 계속 참조할 수 있음. 단점은 같은 수준의 탭 자동완성 사용성이 나오지 않는다는 점인데, 그 부분은 정말 멋지긴 함. 또 Python의 venv 활성화 스크립트처럼 하위 프로세스로 실행되지 않고 source되어야 하는 스크립트에서는 여전히 충돌이 생길 수 있지만, 그런 경우는 드묾

    • zsh에서는 그 자동완성도 됨
  • 쉼표로 시작하는 방식은 텍스트 확장기/텍스트 치환 커뮤니티에서도 흔한 기법임

    • 맞음. 내 vim 별칭 대부분도 ,로 시작함
  • 최근 ~/.local/bin/을 살펴보다가, 내가 넣은 기억이 없는 실행 파일이 수십 개 있는 걸 발견했음
    대부분은 pyside 관련이었지만 다른 스크립트도 있었음. 어떤 스크립트를 내가 직접 썼고 어떤 게 남이 만든 건지 기억하려고 하나씩 열어봐야 했음. 내 스크립트 이름을 쉼표로 시작했다면 훨씬 빨랐을 것이고, 각 스크립트를 왜 만들었는지도 열기 전에 떠올리는 데 도움이 됐을 것임

    • 보통 ~/.local/bin/은 설치된 스크립트용이고, 로컬에서 직접 쓴 것은 ~/bin/에 둠
  • 사양하겠음. 개인 bin$PATH 앞에 두고, 가려진 프로그램을 참조할 때는 /usr/bin이나 /bin을 쓰면 됨
    개인화한 도구 목록은 ~/bin/[Tab]으로 나열할 수 있음

    • 시스템 유틸리티를 내 것으로 가리면서도 같은 이름을 쓰고 싶지는 않아서, 계속 쉼표를 기억해야 한다는 점이 이해되지 않음
      시스템의 grep, 예를 들어 Solaris grep이 마음에 안 들고 내가 선호하는 GNU grep을 쓰고 싶다면, 왜 그냥 그걸 grep으로 두지 않겠음?
  • 이 아이디어를 5년 전에 접한 덕분에 내 셸 요령 모음에 질서를 세울 수 있었음. 별칭과 ~/bin을 합쳐 쉼표 명령이 50개 넘게 있고, 예전의 뒤섞인 상태보다 셸 생활이 훨씬 매끄러워짐

  • 2020년에도 논의됐음: https://news.ycombinator.com/item?id=22778988 (댓글 90개)

'_'를 사용하는것은 어떻까요?