POSIX는 표준 유틸리티에 대한 경로를 보장합니까?


22

C에서 표준 유틸리티 (예 : ps)를 실행하는 가장 쉬운 방법은 무엇입니까?

예를 들어, 표준,합니까 POSIX 보증 ps/bin/ps또는 내가 함께 무엇을 얻을에 PATH 환경 변수를 재설정해야 confstr(_CS_PATH, pathbuf, n);하고 PATH 검색을 통해 유틸리티를 실행?


내가 명령의 수에 대한 POSIX는 말한다 내 머리의 뒤쪽에 있고, 그들 중 (1) 에드 (중요하다 mksh 즉,) 경우 그들이 사용할 수 있습니다, 그들은 또한 있어야 도달 아래 일 /bin, 즉 /bin/ed사용할 수 있어야합니다 ed가 설치된 경우. 지금은 그것을 찾을 수 없지만 LSB가 그것에 의존한다는 것을 알고 있으며 그것을 근거로 버그 보고서를 성공적으로 방어했습니다. 그래서 적어도 어느 정도는 사실이어야합니다. (또는 POSuX가 아닌 다른 것이 었으므로 기억 나지만 나머지는 사실입니다.)
mirabilos

답변:


33

아니, 그것은 주로 그것을 준수하는 시스템을 필요로하지 않는다는 이유로하지 않습니다 기본적으로 , 또는을 준수하는 경우에만 (다른 표준의 배제) POSIX 표준.

예를 들어, Solaris (인증 된 인증 시스템)는 유틸리티가 이전 버전과 호환 /bin되는 이유를 설명합니다. 이 유틸리티 는 간결한 방식으로 작동하는 이유를 설명 하고 XPG의 다른 버전 (현재 병합 된)에 대해 별도의 위치 ( /usr/xpg4/bin, /usr/xpg6/bin...) 에서 POSIX 호환 유틸리티를 제공합니다. POSIX) 표준으로, 실제로는 Solaris의 선택적 구성 요소의 일부입니다.

심지어 sh는 보장되지 않습니다 /bin. Solaris에서는/bin/sh Solaris 10까지 Bourne 쉘 (POSIX 호환이 아님) 이었지만 Solaris 11에서는 여전히 ksh93입니다 (여전히 POSIX 호환은 아니지만 실제로는 그 이상입니다 /usr/xpg4/bin/sh).

C에서, 당신은 exec*p()POSIX 환경 (특히PATH 환경 변수 관련)을 .

PATH환경 변수를 설정할 수도 있습니다

#define _POSIX_C_SOURCE=200809L /* before any #include */
...
confstr(_CS_PATH, buf, sizeof(buf)); /* maybe append the original
                                      * PATH if need be */
setenv("PATH", buf, 1);
exec*p("ps"...);

또는 빌드 시점에 실행하려는 POSIX 유틸리티의 경로를 결정할 수 있습니다 (GNU 시스템과 같은 일부 시스템에서는 POSIXLY_CORRECT준수를 보장하기 위해 변수 설정과 같은 추가 단계가 필요함 ).

다음과 같은 것을 시도해 볼 수도 있습니다.

execlp("sh", "sh", "-c", "PATH=`getconf PATH`${PATH+:$PATH};export PATH;"
                         "unset IFS;shift \"$1\";"
                         "exec ${1+\"$@\"}", "2", "1", "ps", "-A"...);

가 있다는 희망 sh$PATH는 Bourne의이 같은, 또한 거기에 있다는 것을, getconf그것이 POSIX 당신이있는 거 관심의 버전에 대한 하나있다.


그래서 당신은 #을 위해 무엇을합니까!?
여호수아

13
@Joshua : 당신은 /usr/bin/env존재하고 대부분 POSIX 호환 기도합니다 .
케빈

3
@Kevin 또는 palaeo-unix의 단점에 익숙해지고 #를 조정하십시오! 올바른 경로를 사용하십시오.
cas

3
@Kevin : 번호 /usr/bin/env이다 더 적은 휴대용 (실제로)보다 해킹 /bin/sh. POSIX 당, 쉘 스크립트를 작성하는 휴대용 방법은 없습니다 더와 #!전혀 . 파일이 실행 가능하지만 ENOEXEC유효한 바이너리가 아닌 execvp경우 표준 셸을 통해 파일을 실행해야합니다. :-) 물론 실제로 이것은 나쁜 생각이므로 그냥 사용해야 #!/bin/sh합니다.
R ..

2
@GeoffNixon, 당신이 말하는 부분은 _POSIX_C_SOURCE를 사용하지 않거나 사용하고 싶지 않거나 사용하고 싶지 않은 경우에 대한 대안입니다. $PATHC 대신 쉘에서 설정합니다 .
Stéphane Chazelas

3

사실 저는 크게 대답 합니다 . POSIX는 다음을 보장합니다.

  1. 거기 이다 지정된 각 유틸리티의 표준 호환 버전으로 절대 경로 A는,
  2. 그리고이 절대 경로를 찾고이 유틸리티를 실행할 수 있어야합니다.

각 유틸리티가 모든 시스템 ( /bin/ps) 의 특정 디렉토리에 있어야 하는 것은 아니지만 반드시 보장됩니다. 시스템 기본 PATH에서 실행 파일로 찾을 수 있음 을 합니다.

실제로, 표준에서이 작업을 수행하는 유일한 표준 지정 방법을 통해 (C에서)이다 unistd.h의 조합을 통해,의 _CS_PATH 또는 셸에서 ' commandgetconf유틸리티, 즉, PATH="$(command -p getconf PATH)" command -v ps항상 고유의 절대 경로를 반환해야합니다 POSIX 호환을 특정 시스템에 제공됩니다. 즉, 구현 정의 되어있는 동안ps 시스템 기본 PATH 변수에 포함 경로 있지만 이러한 유틸리티 는 항상 지정된 경로 중 하나에서 사용 가능하고 고유하며 호환 가능 해야합니다 .

< unistd.h >, command를 참조하십시오 .


그러나 sh에게는 닭고기와 계란 문제가 있습니다. 그 PATH=$(command -p getconf PATH)는 POSIX 환경에서 POSIX 쉘에서 것이다에만 작동합니다. POSIX는 해당 환경에 들어가는 방법을 명시하지 않고 문서화 만합니다. 예를 들어, Solaris에는 a /usr/xpg4/bin/getconf와 a /usr/xpg6/bin/getconf_CS_PATH있으며 두 개의 서로 다른 표준 버전에 대해 서로 다른 값을 반환 하며 기본값은 도 /usr/xpg4/bin없습니다 . 있다 IIRC 당신에게 XPG4 적합성을 제공한다. /usr/xpg6/bin$PATH/usr/bin/getconf
Stéphane Chazelas

Solaris 11+ (UNIX 03+ 인증) 버전에서도 마찬가지입니까? 필자는 항상```Applications ...를 읽었습니다. getconf PATH에 의해 반환 된 PATH를 조사 하여 반환 된 경로 이름이 절대 경로 이름이며 쉘 내장이 아닌지 확인 해야합니다. 예를 들어, 표준 sh 유틸리티의 위치를 ​​판별하려면 다음을 수행하십시오. command -v sh 일부 구현에서는 다음을 리턴 할 수 있습니다. / usr / xpg4 / bin / sh``` sh이는 기본 쉘에서 POSIX 호환 항목이어야 함을 의미합니다. .
제프 닉슨

1
POSIX 에는 주어진 시스템 getconf의 기본값 $PATH에 명령 이 있어야한다는 말이 없습니다 . 예를 들어, POSIX 환경을 얻으려면 에뮬레이션 계층을 시작해야 할 수 있습니다. 그렇지 않으면 유닉스와 같은 명령을 전혀 실행하지 않습니다 (예를 들어 Windows를 생각하십시오). 당신이 준수하는 환경에되면, getconf PATH 당신은 얻을 것이다 $PATH준수 유틸리티에 도착하지만, 당신이 POSIX 환경에 있다면, 그것은 아마도 이미 사건이었다. 참고 getconf ps반환 할 수 있습니다 ps. 갖는 ps내장하는 것이 허용된다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.