cd
A는 POSIX 위임 쉘 내부 명령 :
간단한 명령으로 명령 이름과 선택적인 인수 목록이 발생하면 다음 작업을 수행해야합니다.
- 명령 이름에 슬래시가 포함되어 있지 않으면 다음 순서의 첫 번째 성공 단계가 발생합니다.
...
- 명령 이름이 다음 표에 나열된 유틸리티 이름과 일치하면 해당 유틸리티가 호출됩니다.
...
cd
...
- 그렇지 않으면 PATH를 사용하여 명령을 검색해야합니다.
명시 적으로 내장되어야한다고 말하지는 않지만 사양은 다음과 같은 설명에서 계속됩니다cd
.
cd는 현재 쉘 실행 환경에 영향을주기 때문에 항상 쉘 일반 내장으로 제공됩니다.
로부터 bash
수동 :
다음 쉘 내장 명령은 Bourne 쉘에서 상속됩니다. 이러한 명령은 POSIX 표준에 지정된대로 구현됩니다.
...
cd
cd [-L|[-P [-e]]] [directory]
나는 당신이 cd
내장 될 필요가없는 아키텍처를 생각할 수 있다고 생각 합니다. 그러나 내장 된 의미를 확인해야합니다. 일부 명령을 수행하기 위해 쉘에 특수 코드를 작성하면 내장 기능에 가까워지고 있습니다. 많이할수록 단순히 빌트인하는 것이 좋습니다.
예를 들어, 셸에 하위 프로세스와 통신하기위한 IPC가있을 수 있으며 cd
디렉토리의 존재 여부와 액세스 권한이 있는지 여부를 확인한 다음 셸과 통신하여 변경을 지시하는 프로그램이 있습니다. 예배 규칙서. 그러나, 당신과 통신하는 프로세스가 자식인지 (또는 특별한 파일 디스크립터, 공유 메모리 등과 같은 자식들과의 특별한 통신 수단을 만드는지) 그리고 프로세스가 실제로 있는지 확인해야합니다. 신뢰할 수있는 cd
프로그램이나 다른 것을 실행하십시오 . 그것은 벌레의 전체 캔입니다.
또는 시스템을 호출 하는 cd
프로그램을 가질 수 있으며, chdir
새로운 쉘에 적용된 모든 현재 환경 변수를 사용하여 새로운 쉘을 시작한 다음 완료되면 부모 쉘을 죽입니다. 1
더 나쁜 것은 프로세스 가 다른 프로세스의 환경을 변경할 수 있는 시스템을 가질 수도 있다는 것입니다 (기술적으로는 디버거 로이 작업을 수행 할 수 있다고 생각합니다). 그러나 이러한 시스템은 매우 취약합니다.
그러한 메소드를 보호하기 위해 점점 더 많은 코드를 추가하는 것을 알게 될 것이며,이를 단순히 내장형으로 만드는 것이 훨씬 간단합니다.
실행 파일이라는 것이 내장 기능을 방해하지는 않습니다. 지목 사항:
echo
과 test
echo
및 test
유틸리티 POSIX 위임 (된다 /bin/echo
및 /bin/test
). 그러나 거의 모든 인기있는 쉘은 내장을 가지고 echo
와 test
. 마찬가지로, kill
프로그램으로 사용 가능한 내장 기능도 있습니다. 다른 것들은 다음을 포함합니다 :
sleep
(공통이 아님)
time
false
true
printf
그러나 명령이 내장 이외의 것이 될 수없는 경우가 있습니다. 그 중 하나는입니다 cd
. 일반적으로 전체 경로를 지정하지 않고 명령 이름이 내장 경로와 일치하면 해당 명령에 적합한 함수가 호출됩니다. 셸에 따라 내장 동작과 실행 파일의 동작이 다를 수 있습니다 (특히 문제가되며echo
, 동작 이 크게 다릅니다 . 동작 을 확실하게하려면을 사용하여 실행 파일을 호출하는 것이 좋습니다. 전체 경로를 설정하고 변수를 설정하십시오 POSIXLY_CORRECT
(그렇더라도 실제 보장은 없습니다).
기술적으로 쉘이기도하고 모든 명령을 내장 한 OS를 제공하는 데 방해가되지 않습니다. 이 극한의 끝에는 모 놀리 식 BusyBox가 있습니다. BusyBox는 단일 바이너리이며, (이 파일 이름에 따라) Almquist Shell ( )을 포함하여 240 개가 넘는 프로그램 중 하나로 작동 할 수 있습니다 ash
. PATH
BusyBox를 실행하는 동안 설정 을 해제 ash
해도 BusyBox에서 사용 가능한 프로그램은 여전히을 지정하지 않고도 액세스 할 수 있습니다 PATH
. 그들은 쉘 자체가 BusyBox에 내장되어 있다는 것을 제외하고는 쉘 내장에 가깝습니다.
당신이 보면 dash
소스, 실행 스레드 (파이프 및 다른 것들을 사용하는 경우 관련 추가 기능을 물론,)이 같은 수 있습니다 :
main
→ cmdloop
→ evaltree
→evalcommand
evalcommand
그런 다음 findcommand
명령이 무엇인지 확인하는 데 사용 합니다. 그것은 내장 인 경우, 다음은 :
case CMDBUILTIN:
if (spclbltin > 0 || argc == 0) {
poplocalvars(1);
if (execcmd && argc > 1)
listsetvar(varlist.list, VEXPORT);
}
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
if (exception == EXERROR && spclbltin <= 0) {
FORCEINTON;
break;
cmdentry.u.cmd
은 struct
( struct builtincmd
)이며, 그 중 하나의 멤버는 함수 포인터이며 일반적인 서명은 main
다음 과 같습니다 (int, char **)
. evalbltin
함수 호출 (내장이 있는지 여부에 따라 eval
두 명령 여부) evalcmd
, 또는이 함수 포인터. 실제 기능은 다양한 소스 파일에 정의되어 있습니다. echo
예를 들면 :
int
echocmd(int argc, char **argv)
{
int nonl;
nonl = *++argv ? equal(*argv, "-n") : 0;
argv += nonl;
do {
int c;
if (likely(*argv))
nonl += print_escape_str("%s", NULL, NULL, *argv++);
if (nonl > 0)
break;
c = *argv ? ' ' : '\n';
out1c(c);
} while (*argv);
return 0;
}
이 섹션의 소스 코드에 대한 모든 링크는 행 번호를 기반으로하므로 통지없이 변경 될 수 있습니다.
1 POSIX 시스템에는 cd
실행 파일이 있습니다.
사이드 노트 :
쉘 동작을 다루는 유닉스와 리눅스에는 훌륭한 글이 많이 있습니다. 특히:
지금까지 나열된 질문에서 패턴을 발견하지 못한 경우 거의 모든 질문에 Stéphane Chazelas가 포함됩니다 .
type
명령 을 사용하는 것이 좋습니다