Linux에서 which 명령을 사용하는 방법

리눅스 환경에서 which 명령어는 쉘이 명령을 실행할 때 실제로 어떤 실행 파일(바이너리)을 사용하는지 확인하는 데 쓰입니다. 만약 컴퓨터에 동일한 프로그램의 여러 버전이 있다면, which를 통해 어떤 버전이 실행될지 정확히 파악할 수 있습니다.

실행 파일과 경로

터미널에서 프로그램을 실행할 때, 쉘(예: 최신 배포판에서 흔히 쓰이는 Bash)은 해당 명령의 실행 파일을 찾아 실행합니다. cd, history, pwd 같은 일부 명령어는 쉘에 내장되어 있어, Bash가 따로 찾을 필요 없이 즉시 실행됩니다.

그러나, Bash는 다른 외부 명령어와 독립 실행형 바이너리 파일은 어떻게 찾을까요? Bash는 ‘경로(path)’라고 불리는 디렉토리 목록을 활용합니다. 각 경로는 특정 디렉토리를 가리키며, Bash는 명령이나 프로그램과 일치하는 실행 파일을 찾을 때까지 이 디렉토리들을 순서대로 검색합니다. 일단 찾으면, 해당 파일을 실행하고 검색을 중단합니다.

echo $PATH 명령어를 사용하면 현재 설정된 경로를 확인할 수 있습니다. 터미널에 다음 명령어를 입력하고 Enter 키를 누르세요.

echo $PATH

출력된 경로 목록은 콜론(:)으로 구분되어 있습니다. 예를 들어, Bash는 아래 디렉토리를 순서대로 검색합니다.

/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin

파일 시스템에는 `/sbin`와 `/bin`처럼 이름이 비슷한 폴더들이 많아 혼란스러울 수 있습니다.

경로의 중요성

만약 `htg`라는 프로그램의 업데이트된 버전이 현재 디렉토리에 있고, 다음 명령어로 실행할 수 있다고 가정해 보겠습니다.

./htg

이 프로그램은 간단히 버전 번호를 출력한 후 종료됩니다. 새 버전은 1.2.138입니다.

현재 작업 디렉토리에서 프로그램을 실행하려면, 파일 이름 앞에 `./`를 붙여야 Bash가 해당 위치를 알 수 있습니다.

만약 이 프로그램을 모든 디렉토리에서 실행하고 싶다면, 실행 파일을 `/usr/bin` 디렉토리로 옮겨야 합니다. 이렇게 하면 Bash는 경로에서 해당 프로그램을 찾을 수 있습니다.

이제, 프로그램 이름 앞에 `./`를 입력할 필요 없이 바로 실행할 수 있습니다. 아래 명령어를 통해 파일을 이동해 봅시다.

sudo mv htg /usr/bin

이제 다음 명령어로 프로그램을 실행해 봅시다.

htg

프로그램이 실행되었지만, 업데이트된 새 버전(1.2.138)이 아닌 이전 버전(1.2.105)이 실행되었습니다.

which 명령어

위에서 설명한 문제 때문에 which 명령어가 만들어졌습니다.

which 명령어는 실행 파일의 위치를 찾아줍니다. 다음은 예시입니다.

which htg

which는 `/usr/local/bin` 디렉토리에서 `htg` 버전을 찾았다고 알려줍니다. 이 경로는 업데이트된 `htg`를 이동한 디렉토리보다 먼저 검색되기 때문에 Bash는 이전 버전의 프로그램을 실행한 것입니다.

하지만, `-a` (all) 옵션을 사용하면, 일치하는 항목을 찾았더라도 계속해서 검색합니다.

which -a htg

이제 경로의 모든 디렉토리에서 일치하는 항목이 모두 나열됩니다.

문제가 명확해졌습니다. 이전 버전의 프로그램이 경로상 먼저 검색되는 디렉토리에 존재합니다. 따라서 새 버전을 설치한 디렉토리보다 먼저 발견된 것입니다.

확인을 위해 다음 명령어를 입력하여 각 버전을 명시적으로 실행해 볼 수 있습니다.

/usr/local/bin/htg
/usr/bin/htg

이것으로 문제 상황이 명확해졌고 해결 방법은 간단합니다.

선택지는 두 가지입니다. `/usr/local/bin` 디렉토리에서 이전 버전을 삭제하거나 `/usr/bin`에 있는 새 버전을 `/usr/local/bin`으로 이동하는 것입니다.

결과 확인

결과가 두 개라고 해서 반드시 두 개의 바이너리 파일이 존재한다는 의미는 아닙니다.

`-a` (all) 옵션과 함께 `which` 명령어를 사용하여 `less` 프로그램의 버전을 찾아보는 예시를 살펴보겠습니다.

which -a less

결과를 보면 `less` 프로그램의 버전이 두 군데에 있다고 나오지만 정말 그럴까요? 리눅스 컴퓨터에 `less`의 서로 다른 두 버전(또는 동일한 버전이 여러 위치에)이 설치되어 있는 것은 이상합니다. 따라서 결과를 곧이곧대로 받아들이지 않고, 조금 더 깊이 살펴보겠습니다.

`ls`, `-l` (긴 목록) 및 `-h` (사람이 읽기 쉽게) 옵션을 사용하여 진행 상황을 확인할 수 있습니다.

ls -lh /usr/bin/less

파일 크기는 9바이트로 보고됩니다! 이는 `less`의 전체 사본이 아님을 의미합니다.

목록의 첫 번째 문자는 `l`입니다. 일반 파일에는 첫 번째 문자로 하이픈(-)이 있습니다. `l`은 심볼릭 링크를 의미하는 기호입니다. 만약 이 세부 사항을 놓쳤다면, `->` 기호 또한 이것이 심볼릭 링크, 일종의 바로 가기라는 것을 알려줍니다. 이 링크는 `/bin`에 있는 `less` 복사본을 가리킵니다.

이제 `/bin`에 있는 `less` 버전으로 다시 시도해 보겠습니다.

ls -lh /bin/less

이 항목은 분명히 “실제” 바이너리 실행 파일입니다. 목록의 첫 번째 문자는 하이픈(-)으로 일반 파일이며 파일 크기는 167KB입니다. 따라서 `less`의 사본은 하나만 설치되어 있지만, 다른 디렉토리에 대한 심볼릭 링크가 존재하는 것입니다. Bash는 경로를 검색할 때 이 디렉토리를 찾습니다.

한 번에 여러 명령어 확인하기

여러 프로그램과 명령어를 한 번에 전달하여 확인할 수 있으며, 순서대로 결과를 보여줍니다.

예를 들어, 다음 명령어를 입력하면:

which ping cat uptime date head

제공한 프로그램 및 명령어 목록을 따라 작동하며, 각 항목에 대한 결과를 나열합니다.

which 자체 확인하기

원한다면 다음 명령어를 입력하여 which 명령어 자체를 확인할 수도 있습니다.

which which

호기심으로 리눅스 파일 시스템을 뒤져보는 것 외에도, 명령어나 프로그램에서 예상했던 동작과 다른 동작이 나타날 때 which 명령어는 가장 유용하게 쓰입니다.

이러한 경우에, which를 사용하여 Bash가 실행하는 명령어가 실제로 사용하려는 명령어인지 확인할 수 있습니다.