PATH 검색에 심볼릭 링크가 포함되어 있습니까?


9

이 사이트에서 POSIX 쉘 표준에 따르면

http://pubs.opengroup.org/onlinepubs/9699919799/

PATH이 실행 파일을 찾는 데 사용하는 방법에 대한 :

"지정된 이름과 적절한 실행 권한을 가진 실행 파일이 발견 될 때까지 각 접두사에 파일 이름을 적용하여 목록을 처음부터 끝까지 검색해야합니다."

글쎄, 이것은 이것이 실제 POSIX 구현에서 작동하는 것처럼 보이지 않습니다 :

man which 말한다 :

"현재 환경에서 실행될 파일 (또는 링크)의 경로 이름을 반환합니다. 인수는 엄격하게 POSIX 호환 쉘에서 명령으로 제공되었습니다. 이는 PATH에서 "심볼 링크를 따르지 않습니다."

좋아,이 상황을 보자.

$ pwd /home/mark

$ echo $PATH /home/mark/bin:...

$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar

여기 PATH, 올바른 이름 의 심볼릭 링크 ls가 있으며 실행 가능 하다고보고되었습니다 .

which 전혀 보지 않고 단지 그것이 지적하는 것에 관심이 있습니다.

그럼에도 불구하고 man which명시 적으로 심볼릭 링크를 따르지 않는다는 사실에도 불구하고 (실제로 which foobar인쇄하지 않기 때문에 그렇지 않다는 foobar1것을 알았습니다) 위에서 언급 한 POSIX 셸 설명서는 결코 PATH알고리즘 에서 심볼릭 링크를 따르는 것을 언급하지 않습니다 .

그렇다면 which기존 쉘이 잘못되었거나 설명서를 이해하지 못합니까?

명확하게 :

기존의 행동을 알고 설명 할 수 있습니다. 내 질문은 "어떻게 작동합니까?"가 아닙니다. 내가 알아

내 질문은 문서에 관한 것입니다 : 내가 인용 한 문서를 따르는 데 실수가 있습니다. 아니면 설명서가 잘못 되었습니까?

동기 부여 : 왜 신경 쓰나요?

글쎄, 나는 구현 자이다. 구현 자마다 요구 사항이 다릅니다. 나를 위해, 현재 POSIX 표준의 단어를 정확히 따라야합니다 (또는 표준 자체가 다소 버그가 있기 때문에 더 정확하게 할 수 있어야합니다). 마치 하나님의 말씀처럼.

이제 표준 문구는 매우 분명합니다. 다음 심볼릭 링크는 언급되지 않았습니다. 다른 곳에서는 수행해야 할 위치가 언급되어 있습니다. 따라서이 경우에는하지 마십시오.

그러나 나는 항상 확인 하기 위해 방법 dashbash행동을 다시 확인합니다 . 물론 dashPOSIX로 청구되었지만 POSIX에 부합하는 작은 버그가 많이 있습니다. bashPOSIX와 관련된 버그는 아직 찾지 못했지만 bash는 실제로 POSIX가 아니며 그 이상입니다.

그래서 당신은 그것을 가지고 있습니다. 그게 내가 걱정하는 이유입니다.


당신은 이해하지 못합니다 : 파일의 심볼릭 링크를 따르지 않습니다 . $PATH심볼릭 링크를 포함 할 수 있습니다. 시도하십시오 which sh.
Ipor Sircer

좋아,하지만 내 경우 $PATH에는 심볼릭 링크가 없습니다.
user322908

거의 모든 상황에서 심볼릭 링크가 투명하게 수행됩니다. 그것들 언급 되지 않은 경우 는 일반적으로 명시 적으로 언급 되지 않습니다 (예 lstat(2):). 예를 들어에 대한 설명 open(2)은의 동작에 대해 말할 때 심볼릭 링크 만 언급합니다 O_CREAT | O_EXCL. 대상 파일이 열릴 것이라고 언급 할 필요는 없습니다.
Barmar

답변:


10

심볼릭 링크 자체의 권한은 관련이 없습니다. 당신이 시도하면 그들을 바꿀 수도 없었습니다.

중요한 것은 기본 파일의 권한입니다.

PATH 디렉토리에 실행 파일에 대한 심볼릭 링크를 포함시키는 것이 좋습니다. 실제로 PATH의 많은 실행 파일이 심볼릭 링크 일 수 있습니다. 예를 들어, 데비안 / 우분투와 같은 시스템에서 :

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Jan 23  2017 /bin/sh -> dash

선적 서류 비치

보낸 사람 man chmod:

chmod는 심볼릭 링크의 권한을 절대 변경하지 않습니다. chmod 시스템 호출은 권한을 변경할 수 없습니다. 기호 링크의 권한이 사용 되지 않기 때문에 이것은 문제가되지 않습니다 . 그러나 명령 행에 나열된 각 기호 링크에 대해 chmod는 지정된 파일의 권한을 변경합니다. 반대로 chmod는 재귀 디렉토리 탐색 중에 발생하는 기호 링크를 무시합니다. [공포도 추가]

셸에는 -x파일이 실행 가능한지 확인하기 위한 테스트 가 있습니다. 시도해 봅시다 :

$ ls -l
total 0
lrwxrwxrwx 1 john1024 john1024 7 Dec 12 23:36 foo -> foobar1
-rw-rw---- 1 john1024 john1024 0 Dec 12 23:36 foobar1
$ [ -x foo ] && echo foo is executable
$ chmod +x foobar1
$ [ -x foo ] && echo foo is executable
foo is executable

따라서으로 찾은 것처럼 which기본 파일이 실행 가능하지 않으면 쉘은 소프트 링크 실행 파일을 고려하지 않습니다.

작동 원리

데비안 시스템에서 which쉘 스크립트입니다. 코드의 관련 섹션은 다음과 같습니다.

 case $PROGRAM in
  */*)
   if [ -f "$PROGRAM" ] && [ -x "$PROGRAM" ]; then
    puts "$PROGRAM"
    RET=0
   fi
   ;;
  *)
   for ELEMENT in $PATH; do
    if [ -z "$ELEMENT" ]; then
     ELEMENT=.
    fi
    if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then
     puts "$ELEMENT/$PROGRAM"
     RET=0
     [ "$ALLMATCHES" -eq 1 ] || break
    fi
   done
   ;;
 esac

보시다시피, -x테스트를 사용하여 파일이 실행 가능한지 확인합니다.

POSIX -x는 다음과 같이 테스트를 지정합니다 .

-x pathname 파일 읽기, 쓰기 및 작성에 정의 된대로
파일을 실행할 권한 (또는 파일 이 디렉토리 인 경우 검색)이 부여 된 파일에 대한 경로 이름이 기존 디렉토리 항목으로 해석되면 true 입니다. 경로 이름을 확인할 수 없거나 경로 이름이 파일을 실행 (또는 검색) 할 권한이있는 파일의 기존 디렉토리 항목으로 해석되는 경우 False입니다. [공포도 추가]

따라서 POSIX는 경로명이 무엇을 확인하는지 확인 합니다 . 즉, 심볼릭 링크를 허용합니다.

POSIX exec 함수

POSIX 간부 인 기능은 심볼릭 링크를 다음과 같습니다. POSIX 사양은 다음과 같이 심볼릭 링크가 원형이거나 너무 깊을 경우보고 될 수있는 오류 조건을 지정하기 위해 계속 진행됩니다.

[ELOOP]
경로 또는 파일 인수를 확인하는 동안 발생하는 기호 링크에 루프가 있습니다.

[ELOOP]
경로 또는 파일 인수를 분석하는 동안 {SYMLOOP_MAX} 이상의 심볼릭 링크가 발견되었습니다.
[ENAMETOOLONG]
경로 인수의 분석에서 기호 링크가 발생하여 대체 된 경로 이름 문자열의 길이가 {PATH_MAX}을 (를) 초과했습니다.


나는 당신이 당신의 대답에 쓴 모든 것을 알고 있습니다. 일이 어떻게 작동하는지 알고 있습니다. 그건 내 질문이 아니다. 내 질문은 문서에 관한 것입니다. 문서를 이해하지 못하는 곳을 알려주세요. 또는 설명서가 잘못되었다고 알려주십시오.
user322908

@ user322908 대부분의 시스템에서 which쉘 스크립트입니다. 따라서 -x내가 보여준 테스트를 사용했을 가능성이 큽니다 . POSIX에 따르면 -x파일이 실행 파일로 "해결"되는지 테스트합니다. 다른 것을보고 있다면 어디를보고 있습니까?
John1024

고마워요. 아파서 죄송합니다 ... 제 질문이 99 %의 질문과 다르다는 것을 깨달았습니다. 다시 한 번, "어떻게" which작동하는지 또는 그것이 -x다른 것인지 아닌지에 관심이 없습니다. 인용 한 문서를 올바르게 따르지 않는 곳을 알고 싶습니다.
user322908

4
@ user322908 POSIX exec기능 은 심볼릭 링크를 따릅니다. POSIX에서 심볼릭 링크 된 파일을 실행할 수 있음을 분명히 나타냅니다.
John1024

2
또한 "경로 이름을 정규화 할 수 없습니다"라는 Ubuntu 17.10 man which 도 확인했습니다 . 그렇다고 링크를 따르지 않는다는 의미는 아닙니다. 이는 관찰 한대로 이름을 "정규화"하지 않는다는 것을 의미합니다.
John1024

3

이 경우 최종 경로를 정식화하지 않고 심볼릭 링크를 투명하게 따릅니다 . 즉, 심볼릭 링크 which인지 아닌지 /home/mark/bin는 신경 쓰지 않습니다. 중요한 것은 파일의 /home/mark/bin/foobar존재 여부 입니다. 그것은 필요가없는 경로를 따라 수동으로 평평하게 심볼릭 링크에 - OS가 스스로 그 잘 할 수 있습니다.

실제로의 which파일 정보에 대해 물어 /home/mark/bin/foobar보면 OS /home/mark/bin가 심볼릭 링크임을 확인하고이를 따르며 foobar대상 디렉토리에서 성공적으로 찾습니다 .

프로그램 이 파일을 사용 open(…, O_NOFOLLOW)하거나 fstatat(…, AT_SYMLINK_NOFOLLOW)파일에 액세스 하지 않는 한 이것이 기본 동작 입니다.

[의견 병합]

쉘 유틸리티는 경우에 따라 쉘 유틸리티를 수행하지만 커널 syscall과 동일 하지는 않습니다. "nofollow"플래그를 지정하지 않으면 모든 파일 관련 호출 기본적으로 심볼릭 링크를 따릅니다. (lstat조차도 마지막 경로를 제외한 모든 경로 구성 요소의 심볼릭 링크를 따릅니다.)

사양에서 심볼릭 링크로 수행 할 작업을 명시 적으로 언급하지 않으면 기본 동작이 사용됩니다. 즉, 경로 알고리즘을 따르는 셸은 심볼릭 링크를 수동으로 확인 하지 않으며 동일한 작업을 수행하는 OS를 명시 적으로 선택 해제하지 않습니다. (각각의 $ PATH 구성 요소를 실행 파일 이름으로 연결합니다.)

which (1) 매뉴얼 페이지에서 심볼릭 링크를 따르지 않는다고 말하면 몇 가지를 의미 할 수 있지만 GNU coreutils 버전은 다음과 같이 말합니다.

둘 중 하나에 심볼릭 링크가있는 경로가 포함되어 있으면 두 개의 동등한 디렉토리가 다른 것으로 간주됩니다.

범위가 훨씬 좁 습니다. 복제본을 제거하기위한 모든 경로 which수동으로 정식화 하려고 시도 하지는 않지만 도구가 일반적으로 OS에 따라 symlink를 선택하지 않는다는 것을 의미하지는 않습니다. 예를 들어, 경우 /bin에 심볼릭 링크 /usr/bin실행 which -a sh돌아갑니다 모두 /bin/sh/usr/bin/sh.


예, 감사합니다.이 모든 것을 알고 있습니다. 내 질문은 일들이 어떻게 작동 하는가가 아니다. 나는 그들이 어떻게 작동하는지 안다. 그것은 내 요점이 아닙니다. 요점은 문서화에 관한 것입니다. 문서를 잘못 따르는 곳은 어디입니까? 또는 설명서가 잘못되었습니다.
user322908

2
문서를 잘못 이해하고 있습니다. 다음 심볼릭 링크를 언급하지 않으면 심볼릭 링크를 수동으로 해결 하지 않지만 일반적인 OS 동작은 여전히 적용됩니다. GNU which매뉴얼 페이지는 다음과 같이 다르게 기술하고있다 : "그중 하나가 심볼릭 링크가있는 경로를 포함 할 때 두 개의 동등한 디렉토리가 다른 것으로 간주 할 것이다."
user1686

네, 감사합니다. 이해하려고 노력하고 있습니다 ... 그러나 ... 목에 통증이 있다는 것을 용서하십시오. "일반적인 OS 동작"이 항상 암시 적으로 심볼릭 링크를 따르는 것은 아닙니다. 그렇지 않은 유틸리티가 많이 있습니다. 상황에 따라 다릅니다.
user322908

1
모든 커널 호출 – chdir, open, chmod, execve ... –는 AT_SYMLINK_NOFOLLOW 등을 지정 하지 않으면 경로와 꼬리에서 심볼릭 링크를 따릅니다 . (lstat는 테일에서 심볼릭 링크를 역 참조하지 않고 나머지 경로에 대해서는 여전히 그렇게합니다.) 따라서 기본 동작은 심볼릭 링크를 따르는 것입니다. 예를 들어, 쉘이 호출 execve("/home/mark/bin/foobar", …)하면 모든 심볼릭 링크가 수행됩니다.
user1686

좋아, 나는 execve인수를 사고 있다고 생각 한다. 실제로 내 구현에서 그것은 execl()똑같다. 답변에이 내용을 포함 시키면 수락하겠습니다.
user322908

1

쉘은 경로 이름 분석 규칙을 준수한다는 점에서 문서를 준수합니다. which설명서를 준수합니다. 두 사람은 약간 다른 일을합니다.

의 결과 which는 링크의 파일 이름과 경로이며 심볼릭 링크가 가리키는 경로가 아닙니다. 이 내용은 매뉴얼 페이지에 나와 있습니다.

명령이 실행되면, 링크는 제 4.13 경로 이름 해상도에 따라 "다음"되어 같은에서 . 파일 실행 관련 절은 다음과 같습니다.

다른 모든 경우에 시스템은 심볼릭 링크의 내용이 빈 문자열 인 경우 [ENOENT]를보고하는 기능으로 경로명 확인에 실패한다는 점을 제외하고 나머지 링크 이름 (있는 경우)에 심볼릭 링크의 내용을 접두어로 붙여야합니다. ] 동등한 진단 메시지를 작성하는 오류 및 유틸리티 또는 기호 링크가 포함 된 디렉토리의 경로 이름이 기호 링크의 내용 대신 사용되어야합니다. 심볼릭 링크의 내용이 문자로만 구성되는 경우 나머지 경로 이름의 모든 선행 문자는 결과 결합 경로 이름에서 생략되고 심볼릭 링크 내용에서 선행 문자 만 남습니다. 접두사가 발생하는 경우 결합 된 길이가 {PATH_MAX}를 초과하고 구현에서이를 오류로 간주하면, 경로 이름 확인은 [ENAMETOOLONG] 오류를보고하는 기능과 동등한 진단 메시지를 작성하는 유틸리티로 실패합니다. 그렇지 않으면, 해결 된 경로명은 방금 생성 된 경로명의 해결이되어야한다. 결과 경로 이름이로 시작하지 않으면 경로 이름의 첫 번째 파일 이름의 선행 작업은 심볼릭 링크가 포함 된 디렉토리로 간주됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.