Dlaczego obowiązkowe narzędzia POSIX nie są wbudowane w powłokę?


45

Celem tego pytania jest odpowiedź na ciekawość, a nie rozwiązanie konkretnego problemu komputerowego. Pytanie brzmi: dlaczego obowiązkowe narzędzia POSIX nie są często wbudowane w implementacje powłoki?

Na przykład mam skrypt, który w zasadzie czyta kilka małych plików tekstowych i sprawdza, czy są one odpowiednio sformatowane, ale uruchomienie na moim komputerze zajmuje 27 sekund z powodu znacznej ilości operacji na łańcuchach. Ta manipulacja ciągiem powoduje tysiące nowych procesów poprzez wywoływanie różnych narzędzi, stąd powolność. Jestem całkiem pewny, że jeśli niektóre media zostały wbudowane, a mianowicie grep, sed, cut, tr, i expr, a następnie skrypt zostanie uruchomiony w sekundę lub mniej (w oparciu o moje doświadczenia w C).

Wydaje się, że byłoby wiele sytuacji, w których wbudowanie tych narzędzi sprawiłoby różnicę między tym, czy rozwiązanie w skrypcie powłoki ma akceptowalną wydajność.

Oczywiście istnieje powód, dla którego nie zdecydowano się na wbudowanie tych narzędzi. Być może posiadanie jednej wersji narzędzia na poziomie systemu pozwala uniknąć używania wielu różnych wersji tego narzędzia przez różne powłoki. Naprawdę nie mogę wymyślić wielu innych powodów, aby utrzymać narzut związany z tworzeniem tak wielu nowych procesów, a POSIX wystarczająco definiuje narzędzia, że ​​różne implementacje nie wydają się dużym problemem, o ile każdy z nich jest POSIX zgodny. Przynajmniej nie tak duży problem, jak nieefektywność posiadania tak wielu procesów.


15
Jeśli 27 sekund jest zbyt wolne, możesz użyć Pythona, Perla lub innego częściowo skompilowanego języka. Możesz też opublikować wolne części skryptu i poprosić o ulepszenia. Może być tak, że używasz trzech lub czterech poleceń, z których może skorzystać jedno (szybsze).
roaima

8
Muszle nie zostały stworzone do ciężkich zadań, niestety, a świat bardzo się zmienił od czasów, kiedy można było uciec tylko za pomocą skryptu powłoki. Zgadzam się z roaimą - każdy rozsądny administrator powinien wybrać Pythona lub Perla i nie oczekiwać, że powłoka zajmie się wszystkim
Sergiy Kolodyazhnyy

16
Głównym celem powłoki jest uruchamianie innych programów, a nie bezpośrednia manipulacja danymi. Z biegiem lat niektóre zewnętrzne programy lub funkcje przez nich dostarczane (globbing, arytmetyka printfitp.) Zostały włączone do powłok, gdy uznano je za wystarczająco użyteczne.
chepner

8
Jeśli opublikujesz swój skrypt na codereview.stackexchange.com, jestem pewien, że recenzenci mogą przedstawić pewne sugestie dotyczące znacznego przyspieszenia twojego skryptu (lub przynajmniej wskazać, dlaczego powinien być napisany w Pythonie / etc zamiast powłoki).
chepner

5
@Kyle: awkto obowiązkowe narzędzie w POSIX, a szczególnie dobrze nadają się (czyli bardzo szybki) w celu wdrożenia skryptów, które można realizować w inny sposób za pomocą sed, cut, tr, grep, i exprw skrypcie powłoki.
Nominal Animal

Odpowiedzi:


11

Skrypty powłoki nie powinny działać z taką prędkością. Jeśli chcesz poprawić szybkość skryptu, wypróbuj go w Perlu. Jeśli nadal jest to zbyt wolne, musisz przejść do języka o typie statycznym, takiego jak java lub c, lub napisać moduł C dla perla, który uruchamia zbyt wolne części.

Shell to pierwszy poziom prototypowania, jeśli możesz udowodnić tę koncepcję za pomocą powłoki, to przejdź do lepszego języka skryptowego, który może wykonać więcej sprawdzania granic, co zająłoby akry powłoki.

Oczekuje się, że system operacyjny Unix będzie zawierać wiele małych programów, które wykonują dobrze zdefiniowane zadania, które składają się na większy obraz. To dobra rzecz, ponieważ dzieli większe programy na części. Spójrz na przykład na qmail i porównaj to z sendmailem. qmail składa się z wielu programów:

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

Wykorzystanie demona sieciowego nie pomoże w wykorzystaniu menedżera kolejek.


OP specjalnie NIE poprosił o sugestie dotyczące poprawy szybkości kodu. Pytanie brzmiało, dlaczego niektóre narzędzia nie są wbudowane, takie jak cdlub pwd.
Stephen C

4
Prawdziwe. Odpowiedzią było wyrażenie różnicy między monolitycznym a podzielonym na przedziały i wskazanie powodu tej korzyści.
Ed Neville,


1
@StephenC cdjest wbudowany - i tak musi być, ponieważ zmiana katalogu roboczego w podprocesie nie wpływa na procesy nadrzędne.
Jonas

67

Dlaczego obowiązkowe narzędzia POSIX nie są wbudowane w powłokę?

Aby być zgodnym z POSIX, wymagany jest system 1, aby zapewnić większość narzędzi jako samodzielne polecenia.

Zainstalowanie ich oznaczałoby, że muszą istnieć w dwóch różnych lokalizacjach, wewnątrz powłoki i poza nią. Oczywiście możliwe byłoby zaimplementowanie wersji zewnętrznej za pomocą otoki skryptu powłoki do wbudowanego narzędzia, ale niekorzystnie wpłynęłoby to na aplikacje nie powłoki wywołujące narzędzia.

Zauważ, że BusyBox podążył ścieżką, którą zasugerowałeś, implementując wiele poleceń wewnętrznie i udostępniając samodzielny wariant za pomocą łączy do siebie. Jednym z problemów jest to, że zestaw poleceń może być dość duży, implementacje są często podzbiorem standardu, więc nie są zgodne.

Należy również zauważyć, że co najmniej ksh93, bashi zshpójść dalej poprzez zapewnienie niestandardowe metody dla uruchomionej powłoce dynamicznie builtins ładunek z bibliotek współdzielonych. Technicznie nic nie stoi na przeszkodzie, aby wszystkie narzędzia POSIX zostały zaimplementowane i udostępnione jako wbudowane.

Wreszcie, tworzenie nowych procesów stało się dość szybką operacją w przypadku nowoczesnych systemów operacyjnych. Jeśli naprawdę odczuwasz problem z wydajnością, możesz wprowadzić ulepszenia, aby skrypty działały szybciej.

1 POSIX.1-2008

Jednak wszystkie standardowe narzędzia , w tym standardowe wbudowane w tabeli, ale nie specjalne wbudowane opisane w Specjalnych wbudowanych narzędziach, powinny być zaimplementowane w sposób umożliwiający dostęp do nich za pośrednictwem rodziny exec działa zgodnie z definicją w tomie Interfejsy systemowe POSIX.1-2008 i może być wywoływany bezpośrednio przez te standardowe narzędzia, które go wymagają (env, find, nice, nohup, time, xargs).


4
To właściwa odpowiedź, ale dodam tylko, że ponieważ interfejs tych narzędzi jest generalnie przez stdin / stdout i tak, nawet jeśli każde z nich zostało zaimplementowane jako wbudowana rutyna w bash, to nadal potrzebowałoby i tak rozwidlać się i tworzyć potoki dla każdego polecenia w potoku, aby zyski były tylko marginalne
Chunko

2
@Chunko Tak. podpowłoki są jednak lżejsze niż procesy rozwidlone / wykonywane.
jlliagre

3
@slebetman Tęsknisz za moim punktem. Podpowłoki nie są ani wątkami, ani wykonywanymi procesami, niezależnie od tego, czy działają w systemie Linux, czy nie. Podpowłoki są tylko klonem ich rodzica, utworzonym przez fork nie, po którym następuje exec; forkjest obecnie bardzo lekką operacją w porównaniu do exec.
jlliagre

3
Zmierzyłem, że noforkwbudowane busybox mają 10-krotnie mniejszy narzut niż noexecwbudowane, które z kolei miały ~ 5-krotnie mniejsze obciążenie niż rozwidlenie + wykonanie osobnego pliku binarnego. Definicje według unix.stackexchange.com/a/274322/29483 Interesujące jest to, że busybox nie noforkwszystko, chociaż wiem, że niektóre kody busybox są skracane przez brak czyszczenia pamięci i po prostu polegają na tym, że są krótkotrwałe.
sourcejedi

1
@jlliagre: W systemie Linux rozwidlenie tworzy proces. Chyba brakuje Ci tego, że w Linuksie zoptymalizowali procesy tak bardzo, że programiści stwierdzili, że nie ma już żadnej korzyści, tworząc coś bardziej lekkiego. Zasadniczo w systemie Linux proces jest tak lekki jak nić.
slebetman

9

Z podręcznika BASH ,

Wbudowane polecenia są niezbędne do wdrożenia funkcjonalności niemożliwej lub niewygodnej do uzyskania za pomocą oddzielnych narzędzi.

Jak jestem pewien, słyszałeś, filozofia UNIX opiera się w dużej mierze na wielu aplikacjach, które mają ograniczoną funkcjonalność. Każdy wbudowany ma bardzo dobry powód, dla którego jest wbudowany. Nie wszystko inne. Myślę, że bardziej interesująca klasa pytań brzmi: „dlaczego dokładnie jest pwd wbudowana?”


2
Jednym słowem: Modułowość
Peschke

2
/ bin / pwd istnieje. Myślę, że cdbyłby to lepszy przykład czegoś, czego nie można wdrożyć jako osobnego narzędzia.
Oskar Skog

1
@OskarSkog To był punkt. cdmusi być wbudowany, pwdnie. Dlaczego więc bashimplementatorzy zdecydowali się to uwzględnić?
Stig Hemmer

1
... który jest obsługiwany przez unix.stackexchange.com/questions/145479 .
JdeBP

@StigHemmer /bin/bashistnieje, ale wciąż jest wbudowany. Zobacz listę wbudowanych plików na gnu.org/software/bash/manual/html_node/…
Stephen C

8

Faceci w AT&T zadawali sobie to samo

Jeśli spojrzysz na historię oprogramowania AT&T Software Toolkit (obecnie nieaktywnego na githubie od czasu odejścia zespołu podstawowego), dokładnie to zrobili z powłoką AT&T Korn, czyli ksh93.

Wydajność zawsze była motywacją dla opiekunów ksh93, a podczas budowania ksh możesz zbudować wiele popularnych narzędzi POSIX jako dynamicznie ładowanych bibliotek. Wiążąc te polecenia z nazwą katalogu, na przykład /opt/ast/bin, możesz kontrolować, która wersja polecenia będzie używana, na podstawie położenia tej nazwy katalogu w $PATH.

Przykłady:

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

Pełna lista znajduje się w repozytorium github ast .

Zauważ, że większość narzędzi ast ma swoje pochodzenie i różni się znacznie od bardziej powszechnych implementacji GNU. Zespół badawczy AT&T przestrzegał oficjalnych standardów, co było sposobem na osiągnięcie interoperacyjności, gdy nie można było współdzielić kodu.


6

Dlatego nie zgromadziliśmy środków na optymalizację oryginalnego narzędzia, aby spełnić każde konkretne pragnienie. Wydaje mi się, że musimy wyjaśnić, ile kosztowało by to konkretne pragnienie.

POSIX wystarczająco definiuje narzędzia, że ​​różne implementacje nie wydają się dużym problemem.

jest to złe założenie :-P.

Systemy Post-POSIX stają się coraz bardziej wydajne i wygodne z dobrych powodów; jako standard po fakcie nigdy nie nadrabia zaległości.

Ubuntu podjął starania, aby przejść do zredukowanej powłoki POSIX dla skryptów, aby zoptymalizować stary proces uruchamiania systemu w wersji V. Nie twierdzę, że to się nie udało, ale spowodowało wiele błędów, które musiały zostać usunięte: „bashisms”, skrypty, które działały pod warunkiem, /bin/shże bashfunkcje były dostępne.

POSIX sh nie jest dobrym językiem programowania ogólnego przeznaczenia. Jego głównym celem jest sprawne działanie jako interaktywna powłoka. Jak tylko zaczniesz zapisywać polecenia w skrypcie, pamiętaj, że zbliżasz się do tarasu Turinga . Np. Nie można wykryć awarii w środku normalnego rurociągu . bashdodano set -o pipefailw tym celu, ale nie jest to POSIX.

Podobne przydatne, ale niestandaryzowane funkcje są oferowane przez prawie każde narzędzie bardziej złożone niż true.

Dla zarysowanej klasy zadania możesz narysować szorstką linię dla Awk, Perl, a obecnie Python. Różne narzędzia zostały stworzone i ewoluowały niezależnie. Czy spodziewałbyś się, że np. GNU Awk zostanie włączony do libutilposixextended?

Nie twierdzę, że mamy teraz jedno ogólnie lepsze podejście, na które mogę wskazać. Mam słabość do Pythona. Awk jest zaskakująco potężny, chociaż byłem sfrustrowany niektórymi cechami specyficznymi dla GNU Awk. Ale chodzi o to, że przetwarzanie dużej liczby łańcuchów osobno (prawdopodobnie z linii plików) nie było celem projektowym powłoki POSIX.


Zastanawiam się, czy wystąpiłaby trudność z powłoką, która zakładałaby, że każde polecenie wykonane z konfigurowalnej listy lokalizacji byłoby traktowane jako wbudowane w przypadkach, w których powłoka rozumiała wszystko o poleceniu? Jeśli skrypt wykonuje skrypt, cat -@fnord foopowłoka powinna o tym zadecydować, ponieważ nie wie, co to -@znaczy, musiałaby wywołać rzeczywiste polecenie, ale biorąc pod uwagę samą cat <foo >barpowłokę, nie trzeba jej odradzać.
supercat

1
Złożoność @supercat.
sourcejedi

2

Pozostaje również pytanie: w którą powłokę chcesz go wbudować?

Większość systemów Unix / Linux ma wiele różnych powłok, które są opracowywane niezależnie (sh / bash / korn / ???). Jeśli wbudujesz narzędzia w powłokę, skończysz z inną implementacją tych narzędzi dla każdej powłoki. Spowodowałoby to narzut i możesz skończyć z różnymi funkcjami / błędami, na przykład grep, w zależności od powłoki, której użyłeś do wywołania.


Zsh jest obecnie bardzo popularny w niektórych kręgach. csh / tcsh od dawna cieszy się dużą popularnością, ale nie sądzę, żebyś dzisiaj dużo go widział. I jest cały pakiet mniej znanych pocisków ...
CVn

Modułowość. W przypadku wbudowanych poleceń należy ponownie skompilować lub ponownie zainstalować powłokę za każdym razem, gdy wprowadzana jest zmiana w jednym z tych wbudowanych elementów.
can-ned_food

1

Wielu odpowiedziało dobrze. Zamierzam jedynie uzupełnić te odpowiedzi. Myślę, że filozofią UNIX jest to, że narzędzie powinno zrobić jedną rzecz i zrobić to dobrze. Jeśli ktoś próbuje stworzyć wszechstronne narzędzie, jest więcej miejsc do porażki. Ograniczenie funkcjonalności w ten sposób sprawia, że ​​zestaw narzędzi jest niezawodny.

Zastanów się również, czy jeśli funkcjonalność, taka jak sed lub grep, została wbudowana w powłokę, czy równie łatwo byłoby wywołać ją z wiersza poleceń, kiedy chcesz?

Podsumowując, zastanów się, niektóre funkcje, które chcesz być w BASH, są w BASH . Na przykład, zdolność dopasowywania RE w BASH jest zaimplementowana przy użyciu operatora binarnego = ~ (zobacz Gramatyka powłoki na stronie podręcznika, aby uzyskać więcej informacji, w szczególności omówienie konstrukcji [[]] dla if ). Jako bardzo szybki przykład załóżmy, że szukam w pliku 2 cyfr szesnastkowych:

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

Jeśli chodzi o funkcjonalność podobną do sed , spójrz pod Rozwijanie parametrów w nagłówku Rozbudowa tej samej strony podręcznika. Zobaczysz wiele rzeczy, które możesz zrobić, które przypominają sed. Najczęściej używam sed, aby dokonać zmiany typu podstawienia w tekście. Uwzględniając powyższe:

# 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

W końcu jednak, czy powyższe jest „lepsze” niż?

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

Argument przeciwko ostatniemu pytaniu można znaleźć pod unix.stackexchange.com/questions/169716/...
phk

1

To chyba historyczny wypadek.

Kiedy UNIX powstał na przełomie lat sześćdziesiątych i siedemdziesiątych XX wieku, komputery nie miały prawie tyle pamięci, co obecnie. W tym czasie byłoby możliwe zaimplementowanie wszystkich tych funkcji jako wbudowanych powłok, ale z powodu ograniczeń pamięci musieliby ograniczyć liczbę funkcji, które mogliby wdrożyć, lub ryzykować brak pamięci i / lub zamianę śmieci problemy.

Z drugiej strony, wdrażając daną funkcjonalność jako osobne programy i wykonując dwa wymagane wezwania systemowe do rozpoczęcia nowego procesu tak łagodnie, jak to możliwe, mogą stworzyć środowisko skryptowe, które nie ma tych problemów i które nadal działa na rozsądnym poziomie prędkość.

Oczywiście, gdy te rzeczy zostaną zaimplementowane jako osobne procesy, ludzie uruchomią je z programów, które nie są powłokami, a następnie muszą tak pozostać, albo nagle całe to oprogramowanie zacznie się psuć.

Nie oznacza to jednak, że nie można dwukrotnie zaimplementować niektórych funkcji, a niektóre powłoki implementują funkcje, które powinny być programami zewnętrznymi jako wbudowane powłoki; np. bash implementuje echopolecenie jako wbudowane, ale jest też/usr/bin/echo

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.