"set"이라는 프로그램이 실행되지 않는 이유는 무엇입니까?

"set"이라는 프로그램이 실행되지 않는 이유는 무엇입니까?

아래와 같이 간단한 C 프로그램을 만들었습니다.

int main(int argc, char *argv[]) {

    if (argc != 5) {
       fputs("Not enough arguments!\n", stderr);
       exit(EXIT_FAILURE);
    }

경로를 수정했습니다등/bash.bashrc이와 같이:

PATH=.:$PATH

나는 이 프로그램을 set.c로 저장하고 다음을 사용하여 컴파일했습니다.

gcc -o set set.c

폴더에

~/Programming/so

그런데 전화를 해보니

set 2 3

아무 일도하지. 텍스트가 나타나지 않습니다.

부르다

./set 2 3

예상했던 결과를 주었다

이전에는 PATH 문제가 발생한 적이 없습니다.

which set

반품 ./set. 따라서 PATH가 올바른 것 같습니다. 무슨 일이에요?

답변1

which를 사용하는 대신가장 필요할 때는 작동하지 않습니다, type다음 명령을 입력할 때 실행될 항목을 결정합니다.

$ which set
./set
$ type set
set is a shell builtin

쉘은 검색하기 전에 항상 내장 함수를 찾으므로 여기에서는 $PATH설정이 $PATH도움이 되지 않습니다.

실행 파일의 이름을 다른 것으로 바꾸는 것이 가장 좋지만 작업에서 프로그램 이름을 지정해야 하는 경우 set셸 함수를 사용할 수 있습니다.

$ function set { ./set; }
$ type set
set is a function
set ()
{
    ./set
}

(이것은 에서 작동 bash하지만 다른 쉘에서는 ksh이를 허용하지 않을 수 있습니다. 보다 이식 가능한 솔루션은 mikeserv의 답변을 참조하십시오.)

이제 입력하면 set를 실행하는 "set"이라는 함수가 실행됩니다 ./set. GNU는 bash내장 함수를 찾고 검색하기 전에 함수를 찾습니다 $PATH. bash 매뉴얼 페이지의 "COMMAND EXECUTION" 섹션에 이에 대한 자세한 정보가 있습니다.

builtincommand및 : help builtin및 에 대한 설명서도 참조하세요 help command.

답변2

setbash(및 아마도 대부분의 다른 쉘)에 내장된 기능입니다. 이는 bash가 함수를 찾을 때 경로를 검색하지 않는다는 것을 의미합니다.

그런데 .보안상의 이유로 경로에 추가하지 않는 것이 좋습니다. 예를 들어, 다른 사용자가 실행 파일을 추가한 후 종료한다고 상상해 보십시오 cd./tmp/tmp/cd

답변3

set아니요오직내장되어 있습니다.POSIX 특수 내장. 명령 검색에서 먼저 발견되도록 표준에서 지정하는 일부 내장 명령이 있습니다. - $PATH검색되지 않음, 함수 이름으로 검색되지 않음 등. 대부분의 내장 명령은 다음과 같습니다.아니요 특별한실제로는필수의POSIX 표준을 준수하여 다음을 수행할 수 있습니다.$PATH 앞으로쉘은 자체 내장 프로시저를 실행합니다. 이는 echo대부분의 사람들에게 해당됩니다.(이와 관련된 표준 준수 여부는 과거 Open Group 메일링 리스트에서 논쟁의 대상이 되었지만), 하지만아니요,,,,,,,,,,,,,,,,,, 또는 의 set,,,,,,,,,,,,,,,,, 또는.trap​​​​​​​​​​breakreturncontinue.:timesevalexitexportreadonlyunsetexec

이들 모두는 셸에 대해 예약된 이름이며 명령 검색의 우선 순위 외에 특별한 속성을 가지고 있습니다. 예를 들어, 표준 호환 쉘에서는 이러한 이름을 사용하여 쉘 함수를 정의할 수 없습니다. 이것은좋은 것- 사람들이 이식 가능한 스크립트를 작성할 수 있게 해줍니다.안전하게. 이는 숙련된 시나리오 작가가 자신의 환경에서 안전하고 보안이 유지되는 기반을 구축할 수 있는 기본 명령입니다. 이 네임스페이스를 침해하는 것은아니요제안.

그러나 해킹하고 싶다면 alias.shell 명령을 사용할 수 있습니다.확장이 해결 방법을 활성화하십시오. alias명령을 읽을 때 확장이 수행되므로 정의에서 이름을 바꾸는 것은 무엇이든 올바르게 set확장되지만 아마도 이러한 이름 중 하나로 확장되어서는 안 됩니다.

그래서 당신은 이것을 할 수 있습니다 :

alias set=./set

...이건 괜찮을 것 같아요.

답변4

문제는 이것이 set내장 쉘이고 가장 좋은 해결책은 다음과 같다는 것입니다.다른 이름을 사용하다실행 가능한 프로그램을 위해.

그런데 지난주에 제가 누군가에게 어떻게 지내는지 물었어요.동일한 이름을 가진 쉘 내장 대신 시스템 명령 실행내가 수락한 해결책은 다음을 통해 명령을 실행하는 것이었습니다 env.

env set 2 3

이 특별한 경우에는 사용하려는 명령이 현재 디렉터리에 있다는 것을 이미 알고 있으며 .해당 경로(현재 작업 디렉터리를 나타내는 데 사용됨)를 입력하여 실행 파일을 직접 실행하는 것이 가장 좋습니다.

./set 2 3

위의 두 솔루션은 모두 쉘에 구애받지 않습니다. 즉, 어떤 쉘을 사용하든 관계없이 작동합니다.

command내장 명령 사용과 같은 제안은 Bash에서 작동하지 않습니다. 이는 단지 쉘을 차단할 뿐입니다.기능실행되는 것부터. 문서화되지는 않았지만 다음을 사용하여 command쉘도 억제된다는 점도 알아냈습니다.핵심 단어. 그러나 쉘의 경우에는 동일하지 않습니다.내장 기능예를 들어 set. 내가 이해한 바로 command는 다른 쉘(예: zsh)과 함께 사용할 수 있습니다.

또한 Bash 내장 기능과 같은 트릭은 \set작동 하지 않습니다."set"'set'별명또는 껍질핵심 단어.

참고: 이 답변은 원래 Eric의 (수락된) 답변에 대한 의견으로 시작되었지만 의견을 수용하기에는 너무 커졌습니다. PATH에 type추가하지 않고 사용을 제안하는 다른 답변은 모두 좋은 답변입니다..

관련 정보