POSIX 필수 유틸리티가 왜 쉘에 내장되어 있지 않습니까?


45

이 질문의 목적은 특정 컴퓨팅 문제를 해결하지 않고 호기심에 답하는 것입니다. POSIX 필수 유틸리티가 쉘 구현에 일반적으로 내장되어 있지 않은 이유는 무엇입니까?

예를 들어, 기본적으로 작은 텍스트 파일을 읽고 형식이 올바른지 확인하는 스크립트가 있지만 상당한 양의 문자열 조작으로 인해 내 컴퓨터에서 실행하는 데 27 초가 걸립니다. 이 문자열 조작은 다양한 유틸리티를 호출하여 수천 개의 새로운 프로세스를 생성하므로 속도가 느려집니다. 나는 유틸리티의 일부 즉, 내장 된 경우 꽤 확신 grep, sed, cut, tr,과 expr, 다음 스크립트가 두 번째로 실행됩니다 이하 (C에서 내 경험을 바탕으로).

이러한 유틸리티를 빌드하면 셸 스크립트의 솔루션이 허용 가능한 성능을 갖는지 여부를 차별화하는 많은 상황이있는 것 같습니다.

분명히, 이러한 유틸리티를 내장하지 않기로 선택한 이유가 있습니다. 시스템 레벨에서 하나의 유틸리티 버전을 사용하면 여러 쉘에서 해당 유틸리티의 여러 가지 버전이 사용되지 않는 것을 피할 수 있습니다. 정말 많은 새로운 프로세스를 생성하는 오버 헤드를 유지 해야하는 다른 많은 이유를 생각할 수 없으며 POSIX는 유틸리티에 대해 충분히 정의하여 각 POSIX 인 한 다른 구현을 갖는 것이 큰 문제가 아닌 것처럼 보입니다. 준수합니다. 최소한 많은 프로세스를 갖는 비 효율성만큼 큰 문제는 아닙니다.


15
27 초가 너무 느리면 Python, Perl 또는 다른 반 컴파일 언어를 사용할 수 있습니다. 또는 스크립트의 느린 부분을 게시하고 개선을 요청하십시오. 하나 (더 빠른 것)가 할 수있는 3 개 또는 4 개의 명령을 사용하고있을 수 있습니다.
roaima

8
불행히도 쉘은 실제로 어려운 작업을 위해 만들어지지는 않았으며 쉘 스크립트만으로 도망 갈 수 있었던 이후로 세상은 크게 변했습니다. 나는 roaima에 동의한다-모든 합리적인 sysadmin은 Python이나 Perl을 위해 가고 쉘이 모든 것을 처리 할 것을
기 대해서는 안된다

16
쉘의 주요 목적은 데이터를 직접 조작하지 않고 다른 프로그램을 실행하는 것입니다. 수년에 걸쳐 일부 외부 프로그램 또는 기능 (글 로빙, 산술 printf등)이 충분히 유용한 것으로 간주 될 때 쉘에 통합되었습니다.
chepner

8
codereview.stackexchange.com에 스크립트를 게시하면 검토자가 스크립트 속도를 크게 높일 수있는 제안을 할 수있을 것입니다.
chepner

5
@Kyle : awk당신이 그렇지 않으면 사용하여 구현할 수 있다는 스크립트를 구현하기 위해 (매우 빠르고입니다) POSIX의 필수 유틸리티입니다, 특히 적합 sed, cut, tr, grep, 그리고 expr쉘 스크립트에서.
공칭 동물

답변:


11

쉘 스크립트는 해당 유형의 속도로 실행되지 않습니다. 스크립트 속도를 향상 시키려면 perl로 시도하십시오. 그래도 속도가 너무 느리면 java 또는 c와 같이 정적으로 유형이 지정된 언어로 이동하거나 너무 느린 부분을 실행하는 perl에 대한 C 모듈을 작성해야합니다.

쉘은 프로토 타이핑의 첫 번째 레벨입니다. 쉘로 개념을 증명할 수 있다면 더 많은 스크립팅 언어로 이동하여 더 많은 범위 검사를 수행 할 수 있습니다.

유닉스 OS에는 더 큰 그림을 구성하는 잘 정의 된 작업을 수행하는 많은 작은 프로그램이 포함될 것으로 예상됩니다. 더 큰 프로그램을 구획화하기 때문에 이것은 좋은 것입니다. 예를 들어 큐메일을보고 sendmail과 비교하십시오. 큐메일은 많은 프로그램으로 구성되어 있습니다 :

http://www.nrg4u.com/qmail/the-big-qmail-picture-103-p1.gif

네트워크 데몬을 악용해도 큐 관리자를 악용하는 데 도움이되지 않습니다.


OP는 특별히 코드 속도 향상에 대한 제안을 요구하지 않았습니다. 문제는 특정 유틸리티가 cd또는 과 같은 내장 기능이 아닌 이유였습니다 pwd.
Stephen C

4
참된. 답은 모 놀리 식과 구획화의 차이를 표현하고이 호의에 이유를 제시하는 것이 었습니다.
Ed Neville


1
@StephenC cd는 기본 제공되며 하위 프로세스에서 작업 디렉토리를 변경해도 상위 프로세스에 영향을 미치지 않기 때문에 실제로 필요합니다.
조나스

67

POSIX 필수 유틸리티가 왜 쉘에 내장되어 있지 않습니까?

POSIX 호환이기 때문에 대부분의 유틸리티를 독립형 명령으로 제공 하려면 시스템 1필요 합니다.

그것들을 내장하면 쉘 내부와 외부의 두 가지 다른 위치에 존재해야 함을 의미합니다. 물론, 쉘 스크립트 랩퍼를 사용하여 외부 버전을 내장 할 수 있지만 쉘을 사용하지 않는 응용 프로그램은 유틸리티를 호출하는 데 불리합니다.

참고 비지 박스는 내부적으로 많은 명령을 구현 자체에 대한 링크를 사용하여 독립 변형을 제공하여 제안 된 경로를했다. 한 가지 문제는 명령 세트가 상당히 클 수 있지만 구현은 종종 표준의 일부이므로 준수하지 않는 것입니다.

적어도 것도 참고 ksh93, bashzsh공유 라이브러리에서 동적으로로드 내장 명령을 실행중인 쉘에 대한 사용자 지정 방법을 제공함으로써 더 이동합니다. 기술적으로 모든 POSIX 유틸리티가 내장되어 제공되는 것을 막을 수있는 것은 없습니다.

마지막으로, 새로운 프로세스 생성은 최신 OS에서 상당히 빠른 작업이되었습니다. 실제로 성능 문제가 발생하면 스크립트 실행 속도가 향상 될 수 있습니다.

1 POSIX.1-2008

그러나 표의 일반 내장 기능을 포함하여 특수 내장 유틸리티에 설명 된 특수 내장 기능을 제외한 모든 표준 유틸리티 는 exec 제품군을 통해 액세스 할 수있는 방식으로 구현되어야합니다. POSIX.1-2008의 시스템 인터페이스 볼륨에 정의 된대로 작동 하며이를 필요로하는 표준 유틸리티 (env, find, nice, nohup, time, xargs)에 의해 직접 호출 할 수 있습니다.


4
이것은 정답이지만, 이러한 유틸리티의 인터페이스가 일반적으로 stdin / stdout을 통해 이루어지기 때문에 모든 유틸리티가 bash의 내장 루틴으로 구현되어 있어도 여전히 여전히 필요합니다. 어쨌든 파이프 라인에서 각 명령에 대한 파이프를 생성하고 파이프를 만들 수 있기 때문에 한계가 있습니다.
Chunko

2
@Chunko 네. 서브 쉘은 포크 / 실행 프로세스보다 가볍습니다.
jlliagre

3
@slebetman 당신은 내 요점을 놓치고 있습니다. 서브 쉘은 Linux에서 실행 중인지 여부에 관계없이 스레드 또는 실행 된 프로세스가 아닙니다. 서브 쉘이 만든 그들의 부모의 클론입니다 fork 하지 다음 exec; fork오늘날에 비해 매우 가벼운 작업 exec입니다.
jlliagre

3
나는 busybox nofork내장을 내장보다 오버 헤드가 10 배 적은 것으로 측정 noexec했으며, 이는 별도의 바이너리의 fork + exec보다 ~ 5 배 더 적은 오버 헤드를 가졌습니다. unix.stackexchange.com/a/274322/29483에 따른 정의 busybox가 nofork메모리를 정리하지 않음으로써 일부 busybox 코드가 단축되고 단기 프로세스에 의존한다는 것을 알지만 busybox가 모든 것이 아니라는 점이 흥미 롭습니다 .
sourcejedi

1
@jlliagre : 리눅스에서 포크는 프로세스를 만듭니다. 당신이 놓칠 수있는 요점은 리눅스에서 프로세스를 너무 최적화하여 개발자가 더 가벼운 것을 만들면 더 이상 이점이 없다는 것을 결정했다는 것입니다. 기본적으로 리눅스에서는 프로세스가 스레드만큼 가볍습니다.
slebetman 2012

9

로부터 BASH 참조 설명서 ,

내장 된 명령은 별도의 유틸리티로는 얻을 수 없거나 불편한 기능을 구현하는 데 필요합니다.

잘 들었 겠지만, UNIX 철학은 기능이 제한적인 여러 응용 프로그램에 크게 의존합니다. 각 내장에는 내장 된 이유가 아주 좋습니다. 다른 모든 것은 아닙니다. 나는 질문이 더 흥미 클래스의 라인을 따라 생각 "이유를 정확히 되어 pwd 내장?"


2
한마디로 : Modularity
Peschke

2
/ bin / pwd가 존재합니다. cd별도의 도구로 구현할 수없는 것이 더 좋은 예 라고 생각 합니다.
Oskar Skog 2012

1
@OskarSkog 그게 요점입니다. cd내장되어 있어야합니다 pwd. 그렇다면 bash구현 자들이 왜 그것을 포함하기로 선택 했습니까?
Stig Hemmer


@StigHemmer /bin/bash는 존재하지만 여전히 내장되어 있습니다. gnu.org/software/bash/manual/html_node/
Stephen C

8

AT & T의 사람들은 그들에게 같은 것을 물었습니다

AT & T 소프트웨어 툴킷의 역사 (핵심 팀이 떠난 이후로 현재 github에 휴면 상태)의 역사를 살펴보면, 이것이 바로 AT & T Korn 쉘 (일명 ksh93)과 관련이 있습니다.

성능은 항상 ksh93 관리자에게 동기 부여의 일부였으며 ksh를 빌드 할 때 많은 공통 POSIX 유틸리티를 동적으로로드 된 라이브러리로 빌드하도록 선택할 수 있습니다. 이러한 명령을와 같은 디렉토리 이름에 바인딩하면 /opt/ast/bin에서 해당 디렉토리 이름의 위치에 따라 사용되는 명령 버전을 제어 할 수 있습니다 $PATH.

예 :

cat chmod chown cksum cmp cp cut date expr fmt head join ln
mkdir mkfifo mktemp mv nl od paste rm tail tr uniq uuencode wc

전체 목록은 github ast 저장소 에서 찾을 수 있습니다 .

대부분의 ast 도구는 자체적 인 출처를 가지고 있으며 일반적인 gnu 구현과는 크게 다릅니다. AT & T 리서치 팀은 코드를 공유 할 수 없을 때 상호 운용성을 달성 할 수있는 공식 표준을 준수했습니다.


6

따라서 우리는 모든 특정 요구를 충족시키기 위해 리소스를 원래 도구를 최적화하도록 마샬링하지 않았습니다. 우리가 설명해야 할 것은이 특정 욕구가 구현하는 데 얼마의 비용이들 것인지입니다.

POSIX는 유틸리티에 대해 충분히 정의하여 다른 구현을 갖는 데 큰 문제가되지는 않습니다.

이것은 나쁜 가정입니다 :-P.

POSIX 이후 시스템은 계속해서 강력하고 편리해졌습니다. 사후 표준으로 실제로는 따라 잡지 않습니다.

우분투는 오래된 System V init 부팅 프로세스를 최적화하기 위해 스크립트를 위해 제거 된 POSIX 셸로 전환하기위한 노력을 시작했습니다. 나는 그것이 실패했다고 말하지는 않지만, "bashisms", /bin/shbash기능을 사용할 수 있다고 가정하는 동안 스크립트가 제거되어야하는 많은 버그를 유발했습니다 .

POSIX sh는 좋은 범용 프로그래밍 언어가 아닙니다. 그것의 주요 목적은 대화 형 쉘로 잘 작동하는 것입니다. 명령을 스크립트에 저장하기 시작하면 튜링 타르트에 접근한다는 점에 유의하십시오 . 예를 들어 일반 파이프 라인 중간에서 오류감지 할 수 없습니다 . 이것을 위해 bash추가 set -o pipefail되었지만 POSIX에는 없습니다.

비슷하지만 유용하지만 표준화되지 않은 기능은 거의 모든 유틸리티에서보다 복잡합니다 true.

개요 작업 클래스의 경우 Awk, Perl 및 현재 Python에 대략적인 선을 그릴 수 있습니다. 다른 도구가 만들어지고 독립적으로 진화했습니다. 예를 들어 GNU Awk가 libutilposixextended에 포함되어있을 것으로 기대하십니까?

나는 우리가 지금 당신에게 지적 할 수있는 보편적으로 더 나은 접근법을 가지고 있다고 말하지 않습니다. 파이썬에 대한 소프트 스팟이 있습니다. Awk는 놀랍게도 강력하지만 GNU Awk에만 해당되는 일부 기능에 좌절했습니다. 그러나 요점은 많은 수의 문자열을 개별적으로 (아마도 파일 라인에서) 처리하는 것이 POSIX 셸의 설계 목표가 아니라는 것입니다.


쉘이 명령에 대한 모든 것을 이해하는 경우 구성 가능한 위치 목록에서 실행 된 명령이 내장 된 것으로 간주되는 쉘에 어려움이 있는지 궁금합니다. 만약 스크립트 cat -@fnord foo가 쉘을 수행한다면 어떤 -@명령이 실제 명령을 호출 해야하는지 모르기 cat <foo >bar때문에 쉘이 다른 프로세스를 생성 할 필요는 없다고 결정해야합니다.
supercat

1
@ 슈퍼 캣의 복잡성.
sourcejedi

2

다음 중 하나의 질문이 있습니다.

대부분의 유닉스 / 리눅스 시스템에는 독립적으로 개발 된 여러 개의 다른 쉘이 있습니다 (sh / bash / korn / ???). 도구를 셸에 빌드하면 각 셸에 대해 이러한 도구를 다르게 구현하게됩니다. 이로 인해 오버 헤드가 발생하고이를 호출하는 데 사용한 쉘에 따라 grep과 같은 다른 기능 / 버그가 생길 수 있습니다.


zsh는 요즘 일부 서클에서 꽤 인기가 있습니다. csh / tcsh는 역사적으로 큰 추종자를 가지고 있었지만 오늘날 많은 것을 보지 않을 것이라고 생각합니다. 그리고 덜 알려진 쉘들도 있습니다.
CVn

모듈성. 내장 기능을 사용하면 내장 기능 중 하나가 변경 될 때마다 셸을 다시 컴파일하거나 다시 설치해야합니다.
can-ned_food

1

많은 사람들이 잘 대답했습니다. 나는 그 대답을 칭찬하려고합니다. 유닉스 철학은 도구 가 한 가지 일을 잘 수행해야한다는 것입니다. 모든 것을 포괄하는 도구를 만들려고하면 실패 할 여지가 더 많습니다. 이러한 방식으로 기능을 제한하면 신뢰할 수있는 도구 세트가 만들어집니다.

또한 sed 또는 grep 과 같은 기능 이 쉘에 내장되어 있으면 원하는 때 명령 행에서 호출하기가 쉬울까요?

마지막으로, BASH있기를 원하는 일부 기능 은 BASH에 있습니다. 예를 들어, BASH에서 RE 매칭 기능은 = ~ 이항 연산자를 사용하여 구현됩니다 (자세한 내용 은 if 에 대한 [[]] 구문에 대한 설명은 매뉴얼 페이지의 셸 문법 참조 ). 매우 빠른 예를 들어, 파일에서 2 개의 16 진수를 검색한다고 가정 해보십시오.

while read line; do
    if [[ $line =~ 0x[[:xdigit:]]{2} ]]; then
        # do something important with it
    fi
done < input_file.txt

에 관해서는 나오지도 같은 에서 매개 변수 확장에 따라 기능, 모양 확장 제목 같은 사람 페이지. sed를 연상시키는 당신이 할 수있는 많은 것들을 보게 될 것입니다. 대체 sed를 사용하여 대체 유형을 텍스트로 변경합니다. 위의 건물 :

# this does not take into account the saving of the substituted text
# it shows only how to do it
while read line; do
    ${line/pattern/substitution}
done < input_file.txt

결국, 위의 "보다 낫다"는 것입니까?

grep -E "[[:xdigit:]]{3}" input_file.txt
sed -e 's/pattern/substitution/' input_file.txt

마지막 질문에 대한 논쟁은 unix.stackexchange.com/questions/169716/…
phk

1

이것은 역사적인 사고라고 생각합니다.

1960 년대 후반과 1970 년대 초 유닉스가 만들어 졌을 때 컴퓨터는 오늘날만큼 메모리가 부족했습니다. 당시에는이 모든 기능을 셸 내장으로 구현할 수 있었지만 메모리 제한으로 인해 구현할 수 있거나 메모리 부족 및 / 또는 스왑 휴지통 위험을 감수 할 수있는 기능의 양을 제한해야했습니다. 문제.

반면에, 주어진 기능을 별도의 프로그램으로 구현하고 가능한 한 새로운 프로세스를 시작하기 위해 필요한 두 개의 시스템 호출을 작성함으로써 문제가없고 합리적으로 실행되는 스크립팅 환경을 만들 수 있습니다 속도.

물론 일단 이러한 프로세스가 별도의 프로세스로 구현되면 사람들은 쉘 이 아닌 프로그램에서 시작하여 그 상태를 유지해야합니다. 그렇지 않으면 갑자기이 소프트웨어가 모두 깨지기 시작합니다.

그러나 일부 기능을 두 번 구현할 수는 없으며 실제로 일부 쉘은 쉘 내장으로서의 외부 프로그램이어야하는 일부 기능을 구현합니다. 예를 들어, bash는 echo명령을 내장으로 구현 하지만/usr/bin/echo

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