Próbowałem which cd
i nie podałem ścieżki, ale zamiast tego zwróciłem kod wyjścia 1 (zaznaczony za pomocą echo $?
). Sam coreutil cd
działa, więc plik wykonywalny powinien tam być, prawda? Uruchomiłem również find
for cd
, ale nie pokazano pliku wykonywalnego. Jak to jest wtedy realizowane?
Aktualizacja:
Nie wiem, czy powinienem o to zapytać w innym poście, ale ponieważ myślę, że tutaj jest dobrze, rozwijam (?) Ten post ... Więc odpowiedź była w rzeczywistości dość prosta, nie można tego wykonać - ponieważ to jest Wbudowane - Ale znalazłem, że niektóre wbudowane (powłoka bash w Fedorze) mają pliki wykonywalne! Więc wbudowane -> żaden plik wykonywalny nie jest poprawny, jak sądzę? Być może odpowiedź wyjaśniająca, czym właściwie są wbudowane polecenia (wbudowane polecenia?), O co tu chodzi, zamiast skupiać się bardziej na cd
... Niektóre dobre linki zamieszczone wcześniej wskazują, że wbudowane programy nie są programami ... więc czym one są? Jak oni pracują? Czy to tylko funkcje czy wątki powłoki?
źródło
type
poleceniacd
musi być wbudowany: dlaczego cd nie jest programem? a ten, dlaczegotype
jest lepszy niżwhich
: Dlaczego nie użyć „który”? Czego więc użyć?Odpowiedzi:
Polecenie
cd
nie może być plikiem wykonywalnymW powłoce
cd
służy do „przejścia do innego katalogu” lub, bardziej formalnie, do zmiany bieżącego katalogu roboczego (CWD). Niemożliwe jest zaimplementowanie tego jako zewnętrznego polecenia:Katalog należy do procesu
Obecny katalog roboczy to katalog służący do interpretacji ścieżek względnych w celu uzyskania pełnej ścieżki dostępu do plików. W wielu miejscach stosowane są ścieżki względne, a interpretacja w jednym procesie nie powinna wpływać na inny proces.
Z tego powodu każdy proces ma własny bieżący katalog roboczy.
cd
dotyczy na przykład zmiany bieżącego katalogu roboczego procesu powłokibash
.Gdyby było to polecenie zewnętrzne, plik wykonywalny na ścieżce, uruchomienie tego pliku stworzyłoby proces z własnym katalogiem roboczym, bez wpływu na proces bieżącej powłoki. Nawet jeśli polecenie zewnętrzne zmieniłoby katalog, zmiana ta zniknie po zakończeniu procesu zewnętrznego.
Polecenia wbudowane w powłokę
Dlatego nie ma sensu uruchamiać zewnętrznego polecenia dla zadania
cd
. Komendacd
musi zastosować zmianę do aktualnie uruchomionego procesu powłoki.Aby to zrobić, jest to „wbudowane polecenie” powłoki.
Wbudowane polecenia to polecenia, które zachowują się podobnie do poleceń zewnętrznych, ale są zaimplementowane w powłoce (więc
cd
nie są częścią coreutils). Umożliwia to komendzie zmianę stanu samej powłoki, w tym przypadku wywołaniechdir()
zobacz (patrzman 2 chdir
);O
which
Teraz odpowiedź na pytanie tytułowe jest łatwa:
komenda wykonywalna
which
nie może nam powiedzieć, że cd jest komendą wbudowaną, ponieważ komenda wykonywalna nie wie nic o kompilacjach.Alternatywny
type -a
Alternatywnie
which
możesz użyćtype -a
; Może zobaczyć wykonywalne polecenia i wbudowane; Dodatkowo widzi aliasy i funkcje - również zaimplementowane w powłoce:źródło
cd
wbudowana jest powłoka.cd
jest wbudowaną powłoką z mandatem POSIX :Chociaż nie mówi to wyraźnie, że musi to być wbudowany, specyfikacja mówi dalej w opisie
cd
:Z
bash
instrukcji :Podejrzewam, że można pomyśleć o architekturze, w której
cd
nie musi być wbudowany. Musisz jednak zobaczyć, co oznacza wbudowany. Jeśli napiszesz specjalny kod w powłoce, aby zrobić coś dla jakiegoś polecenia, zbliżasz się do wbudowania. Im więcej robisz, tym lepiej jest mieć wbudowaną funkcję.Na przykład, możesz mieć powłokę z IPC do komunikowania się z podprocesami, i byłoby
cd
program, który sprawdzałby istnienie katalogu i czy masz uprawnienia dostępu i to, a następnie komunikowałby się z powłoką, aby nakazał jej zmianę informator. Będziesz jednak musiał sprawdzić, czy proces komunikowania się z tobą jest dzieckiem (lub zastosuj specjalne środki komunikacji tylko z dziećmi, takie jak specjalny deskryptor pliku, pamięć współdzielona itp.) I czy proces jest w rzeczywistości uruchamianie zaufanegocd
programu lub czegoś innego. To cała puszka robaków.Lub możesz mieć
cd
program, który wywołujechdir
system, i uruchamia nową powłokę ze wszystkimi bieżącymi zmiennymi środowiskowymi zastosowanymi do nowej powłoki, a następnie zabija swoją powłokę macierzystą (jakoś) po zakończeniu.1Co gorsza, możesz nawet mieć system, w którym proces może zmieniać środowiska innych procesów (myślę, że technicznie można to zrobić za pomocą debuggerów). Taki system byłby jednak bardzo, bardzo wrażliwy.
Przekonasz się, że dodajesz coraz więcej kodu, aby zabezpieczyć takie metody, i znacznie łatwiej jest po prostu zrobić to wbudowanym.
To, że coś jest plikiem wykonywalnym, nie uniemożliwia jego wbudowania. Przykładem:
echo
itest
echo
itest
są narzędziami wymaganymi przez POSIX (/bin/echo
i/bin/test
). Jednak prawie każda popularna powłoka ma wbudowaneecho
itest
. Podobniekill
jest również wbudowany, który jest dostępny jako program. Inne obejmują:sleep
(nie tak często)time
false
true
printf
Są jednak przypadki, w których polecenie nie może być niczym innym jak wbudowanym. Jednym z nich jest
cd
. Zazwyczaj, jeśli pełna ścieżka nie jest określona, a nazwa polecenia odpowiada nazwie wbudowanego, wywoływana jest funkcja dostosowana do tego polecenia. W zależności od powłoki zachowanie wbudowanego i pliku wykonywalnego może się różnić (jest to szczególnie problemecho
, ponieważ ma on bardzo różne zachowania . Jeśli chcesz być pewien zachowania, lepiej jest wywołać plik wykonywalny przy użyciu pełną ścieżkę i ustaw zmienne takie jakPOSIXLY_CORRECT
(nawet wtedy nie ma prawdziwej gwarancji).Technicznie nic nie stoi na przeszkodzie, aby zapewnić system operacyjny, który jest również powłoką i ma wszystkie polecenia jako wbudowane. Blisko tego skrajnego końca jest monolityczny BusyBox . BusyBox to pojedynczy plik binarny, który (w zależności od nazwy, z którą jest wywoływany) może zachowywać się jak dowolny z ponad 240 programów , w tym Almquist Shell (
ash
). Jeśli rozłączysz sięPATH
podczas uruchamiania BusyBoxash
, programy dostępne w BusyBox są nadal dostępne bez określaniaPATH
. Zbliżają się do wbudowania powłoki, z wyjątkiem tego, że sama powłoka jest rodzajem wbudowania w BusyBox.Studium przypadku: The Debian Almquist Shell (
dash
)Jeśli spojrzysz na
dash
źródło, wątek wykonania jest mniej więcej taki (oczywiście z dodatkowymi funkcjami związanymi z użyciem potoków i innych rzeczy):main
→cmdloop
→evaltree
→evalcommand
evalcommand
następnie używafindcommand
do ustalenia, czym jest polecenie. Jeśli jest wbudowany, to :cmdentry.u.cmd
jeststruct
(struct builtincmd
), którego jednym z członków jest wskaźnik funkcji, z podpisem typowymain
:(int, char **)
. Teevalbltin
wywołania funkcji (w zależności od tego, czy wbudowany jesteval
komenda lub nie) alboevalcmd
, czy funkcja ta wskazówka. Rzeczywiste funkcje są zdefiniowane w różnych plikach źródłowych.echo
, na przykład jest :Wszystkie łącza do kodu źródłowego w tej sekcji są oparte na numerach wierszy, więc mogą ulec zmianie bez powiadomienia.
1 Systemy POSIX mają
cd
plik wykonywalny .Dygresja:
Istnieje wiele doskonałych postów w systemach Unix i Linux, które dotyczą zachowania powłoki. W szczególności:
cd
polecenia zewnętrznego?źródło
cd
tekst pomocyhelp cd
(to samo dla wszystkich poleceń wbudowanych w powłokę)help
jest to wbudowane bash (dla zsh, torun-help cd
)cd
musi być tak wbudowany w powłokę ... ale oparty na tym, jak właściwości procesu i ich przesyłanie działają w systemie UNIXcd
jako wbudowana powłoka, jest jedyną prostą implementacją. Zobacz odpowiedź Volkera Siegela .Nie można znaleźć pliku wykonywalnego,
cd
ponieważ go nie ma.cd
jest wewnętrznym poleceniem twojej powłoki (npbash
.).źródło
z
man which
:Jak widać z opisu
which
, to tylko sprawdzeniePATH
. Więc jeśli wdrożysz jakieśbash function
, nic ci to nie pokaże. Lepiej używaćtype
polecenia razem zwhich
.Na przykład w
ls
poleceniu Ubuntu aliasowanym dols --color=auto
.A jeśli zaimplementujesz funkcję testową
hello
:which
nic nie pokazuje. Aletype
:W Twoim przypadku:
Oznacza to, że
cd
jest wbudowaną powłoką , jest w środkubash
. Wszystkie wbudowane bash opisaneman bash
w sekcji KOMENDY WBUDOWANE SHELLźródło
manwhich
.which
, używajtype
.