웹에는 사람들을 가르칠 수 있는 기사/자료가 너무 많습니다.어떻게PATH
절대 경로 대신 등의 약어를 사용하여 명령줄 인터페이스에서 사용할 수 있도록 환경 변수를 설정합니다 .java
python
내가 알고 싶은 것은비하인드 스토리명령을 입력하고 Enter를 누르면(예:브라우저에 URL을 입력하면 어떻게 되나요?).
내 추측은 다음과 같습니다.
- 읽기 명령(올바른 인수를 얻기 위해 표준 입력 구문 분석/전처리
$@
) - 명령 검색
- 명령 실행(프로그램 시작, 메모리 소비, stdout/stderr에서 쉘로)
$PS#
관련 환경 변수(예:$PROMPT
등) 를 통해 시뮬레이터를 다시 렌더링합니다.
제가 가장 알아보고 있는 부분이 바로 명령어 조회입니다. 분명히 $PATH
일부 배경 기능에 의해 소비되고 :
/를 구분 기호로 ;
구분했는데 무슨 일이 일어나고 있는 걸까요? 해시 테이블(키: 파일의 기본 이름, 값: 파일의 절대 디렉터리 이름)을 사용하여 이러한 경로 또는 다른 후크 아래에 바이너리를 저장합니까?
참고: 현재 환경에서 명령을 사용할 수 있는지 확인하는 데 사용할 수 있기 때문에 처음에는 해시 테이블인 줄 알았습니다. [ -z hash [command] ]
그러나 사용하면 예상대로 작동 hash | grep python
하지만 출력에서 아무것도 얻지 못합니다 . which python
(메커니즘은 쉘에 따라 다를 수 있지만 더 깊이 이해하고 싶습니다.)
답변1
예상할 수 있듯이 정확한 동작은 셸에 따라 다르지만 기본 기능 수준은 POSIX에 의해 지정됩니다.
표준 쉘 명령 언어로 명령 검색 및 실행(대부분의 쉘은 이것의 상위 집합을 구현합니다.) 많은 경우가 있지만 현재는 PATH
가 사용되는 경우에만 관심이 있습니다. 이 경우:
XBD 환경 변수에 설명된 대로 PATH 환경 변수를 사용하여 명령을 검색해야 합니다.
그리고
검색이 성공한 경우:
[...]
쉘은 별도의 유틸리티 환경에서 이 유틸리티를 실행하며 다음을 호출하는 것과 동일합니다.
execl()
기능 [...] 및길매개변수는 검색 결과의 경로 이름으로 설정됩니다.
실패한 경우 실행이 실패하고 종료 코드 127과 오류 메시지가 반환됩니다.
특히 이 동작은 execvp
기능과 일치합니다. 모든 exec*
함수는 실행될 프로그램의 파일 이름, 일련의 인수( argv
프로그램의 매개변수가 됨) 및 환경 변수 세트를 허용합니다. lookup 을 사용하는 버전의 경우 PATH
,POSIX는 정의합니다:
논쟁문서새 프로세스 이미지 파일을 식별하는 경로 이름을 구성하는 데 사용되는 경로 이름 [...] 이 파일의 경로 접두어는 환경 변수 PATH로 전달된 디렉터리를 검색하여 얻습니다.
이 변수는 파일 이름으로만 알려진 실행 파일을 검색할 때 특정 기능 및 유틸리티가 적용하는 일련의 경로 접두사를 나타내야 합니다. 접두사는 <콜론>( ':' )으로 구분해야 합니다. 길이가 0이 아닌 접두사가 이 파일 이름에 적용될 때 접두사가 <슬래시>로 끝나지 않으면 접두사와 파일 이름 사이에 <슬래시>를 삽입해야 합니다. 길이가 0인 접두사는 현재 작업 디렉터리를 나타내는 오래된 기능입니다. 두 개의 인접한 <콜론> 문자( "::" ), 목록의 나머지 부분 앞의 첫 번째 <콜론> 또는 목록의 나머지 부분 뒤의 후행 <콜론>으로 나타납니다. 엄격하게 호환되는 응용 프로그램은 실제 경로 이름(예: .)을 사용하여 PATH의 현재 작업 디렉터리를 나타내야 합니다.지정된 이름과 적절한 실행 권한을 가진 실행 파일을 찾을 때까지 각 접두사에 파일 이름을 적용하여 목록을 처음부터 끝까지 검색해야 합니다.. 찾고 있는 경로 이름에 <슬래시>가 포함되어 있으면 경로 접두어로 검색을 수행하면 안 됩니다. 경로 이름이 <slash>로 시작하면 지정된 경로가 확인됩니다(참조:경로명 확인). PATH가 설정되지 않거나 null로 설정된 경우 경로 검색은 구현에 따라 정의됩니다.
내용이 좀 길어서 요약하자면 다음과 같습니다.
- 프로그램 이름
/
에 (슬래시, U+002F SOLIDUS)가 포함되어 있으면 경로로 간주됩니다.평범한 패션을 클릭하고 이 프로세스의 나머지 부분을 건너뜁니다. 쉘의 경우 이러한 상황은 기술적으로 발생하지 않습니다(쉘 규칙이 이미 이를 처리하고 있기 때문입니다). - 의 값은
PATH
각 콜론에서 구성 요소로 나누어지며, 각 구성 요소는 왼쪽에서 오른쪽으로 처리됩니다. 특별한(역사적) 경우로 비어 있지 않은 변수의 빈 부분은.
(현재 디렉터리)로 처리됩니다. - 각 구성요소에 대해 연결을 통해 프로그램 이름이 끝에 추가되고
/
, 해당 이름의 파일이 존재하는지 확인하고, 존재하는 경우 유효한 실행(+x) 권한도 확인합니다. 이러한 검사 중 하나라도 실패하면 프로세스는 다음 구성 요소로 계속됩니다. 그렇지 않으면 명령이 경로를 확인하고 검색을 완료합니다. - 구성요소가 부족하면 검색이 실패합니다.
- 아무것도 없거나
PATH
존재하지 않는다면 원하는 대로 하세요.
실제 셸에는 조회 전에 발견되는 내장 명령이 있으며, 종종 별칭 및 함수와 함께 표시됩니다. 그것들은 와 상호작용하지 않습니다 PATH
.POSIX는 이에 대한 몇 가지 동작을 정의합니다., 쉘에 더 많은 것이 있을 수 있습니다.
대부분의 작업을 사용자가 대신 수행할 수 있지만 exec*
실제로 셸은 특히 캐싱 목적으로 이 조회 자체를 구현할 수 있지만 빈 캐시 동작은 유사해야 합니다. 여기서 쉘은 상당히 넓은 자유도를 가지며 코너 케이스에서는 약간 다른 동작을 보입니다.
당신이 발견했듯이 Bash해시 테이블 사용이전에 본 명령의 전체 경로가 기억되고 hash
이 기능을 사용하여 테이블에 액세스할 수 있습니다. 명령을 처음 실행할 때 검색을 수행하고 결과를 찾으면 테이블에 추가하므로 다음에 시도할 때 찾을 필요가 없습니다.
반면에 zsh에서는 PATH
일반적으로 쉘이 시작될 때 전체 검색이 수행됩니다. 조회 테이블은 검색된 모든 명령 이름으로 미리 채워져 있으므로 일반적으로 런타임 조회가 필요하지 않습니다(새 명령이 추가되지 않는 한). 이전에 존재하지 않았던 명령을 완료하기 위해 Tab 키를 사용하려고 하면 이런 일이 발생하는 것을 알 수 있습니다.
예를 들어 매우 가벼운 쉘은 dash
시스템 라이브러리에 가능한 한 많은 동작을 위임하는 경향이 있으며 과거 명령 경로를 기억하지 않습니다.