Dlaczego ls
jego wykonanie wymaga osobnego procesu? Znam powód, dla którego takich poleceń cd
nie można wykonać za pomocą mechanizmu rozwidlenia, ale czy jest coś złego, jeśli ls
zostanie wykonane bez rozwidlenia?
Dlaczego ls
jego wykonanie wymaga osobnego procesu? Znam powód, dla którego takich poleceń cd
nie można wykonać za pomocą mechanizmu rozwidlenia, ale czy jest coś złego, jeśli ls
zostanie wykonane bez rozwidlenia?
Odpowiedzi:
Odpowiedź jest mniej więcej taka, ls
jak zewnętrzny plik wykonywalny. Możesz zobaczyć jego lokalizację, uruchamiając type -p ls
.
Dlaczego więc nie jest ls
wbudowany w powłokę? Dlaczego tak ma być? Zadaniem powłoki nie jest uwzględnienie wszystkich dostępnych poleceń, ale zapewnienie środowiska, w którym można je uruchomić. Niektóre współczesne powłoki mają echo
, printf
i ich podobne, wbudowane, które technicznie nie muszą być wbudowane, ale są tworzone ze względu na wydajność, gdy są uruchamiane wielokrotnie (głównie w ciasnych pętlach). Bez ich wbudowania powłoka musiałaby rozwidlać i wykonywać nowy proces dla każdego wywołania do nich, co może być bardzo wolne.
Przynajmniej uruchomienie ls
zewnętrznego pliku wykonywalnego wymaga uruchomienia jednej z rodziny wywołań systemowych exec. Możesz to zrobić bez rozwidlenia, ale zastąpiłoby to podstawową powłokę, której używasz. Aby zobaczyć, co dzieje się w tym przypadku, wykonaj następujące czynności:
exec ls; echo "this never gets printed"
Ponieważ obraz procesu powłoki został zastąpiony, bieżąca powłoka nie jest już dostępna po wykonaniu tej czynności. Aby powłoka mogła nadal działać po uruchomieniu ls, polecenie musiałoby być wbudowane w powłokę.
Forking pozwala na zastąpienie procesu, który nie jest twoją podstawową powłoką, co oznacza, że możesz dalej uruchamiać swoją powłokę.
echo
, printf
itp
cd
zewnętrzny plik wykonywalny nie jest?
cd
wykonywalny w POSIX systemów operacyjnych ( patrz tutaj ). Jeśli jednak chcesz faktycznie używać chdir () w bieżącym procesie, musisz go wbudować w powłokę.
The Bash Reference Manual stany:
Wbudowane polecenia są niezbędne do wdrożenia funkcjonalności niemożliwej lub niewygodnej do uzyskania za pomocą oddzielnych narzędzi.
Oznacza to, że pociski zostały zaprojektowane, aby tylko to wbudowanych komend, jeżeli:
ls
Komenda nie pasuje do żadnej z powyższych WYMAGANIA.
Jednak tutaj nie ma ograniczeń programistycznych, które uniemożliwiałyby ls
implementację jako wbudowanej, która działa w tym samym procesie co interpreter bash. Przyczyny projektowania poleceń, które nie są implementowane jako wbudowane powłoki:
Jeśli chodzi o pierwszy powód - chcesz, aby powłoka była jak najbardziej niezależna i odporna. Nie chcesz, aby powłoka utknęła na ls
wierzchowcu NFS, który „nie odpowiada, wciąż próbuje”.
Jeśli chodzi o drugi powód - w wielu przypadkach możesz chcieć użyć powłoki dla systemu, który używa Busybox lub innego systemu plików, który ma inną ls
implementację. Lub nawet użyj tego samego źródła powłoki w systemach operacyjnych, które mają różne ls
implementacje.
Odnośnie trzeciego powodu - dla takich wyrażeń, find . -type d | xargs ls -lad
które byłyby trudne lub niemożliwe do zaimplementowania ls
w tym samym procesie, co interpreter powłoki.
Odnośnie czwartego powodu - wykonanie niektórych ls
poleceń może zająć dużo czasu. W międzyczasie możesz chcieć, aby powłoka kontynuowała wykonywanie czegoś innego.
Uwaga: Patrz to pomocne stanowiska przez Warren Younga w odpowiedzi na podobne pytanie.
ls
do procesu zewnętrznego. Można to zrobić, ale byłoby to skomplikowane.
bash
wyjście alias | grep ls
. wkładcat /etc/passwd | while read a; do echo "$a"; done
ls
nie wymaga osobnego procesu. Bardzo niewiele poleceń wymaga osobnego procesu: tylko te, które wymagają zmiany uprawnień.
Zasadniczo powłoki implementują polecenia jako wbudowane tylko wtedy, gdy polecenia te muszą zostać zaimplementowane jako wbudowane. Polecenia jak alias
, cd
, exit
, export
, jobs
, ... trzeba czytać lub modyfikować jakiś wewnętrzny stan powłoki, a zatem nie mogą być oddzielne programy. Polecenia, które nie mają takich wymagań, mogą być osobnymi poleceniami; w ten sposób można je wywoływać z dowolnej powłoki lub innego programu.
Patrząc na listę wbudowanych poleceń bash, tylko następujące wbudowane elementy mogą być zaimplementowane jako osobne polecenia. W przypadku niektórych z nich nastąpiłaby niewielka utrata funkcjonalności.
command
- ale straci swoją przydatność w sytuacjach, w których PATH
może nie być poprawnie skonfigurowany, a skrypt korzysta z niego command
w ramach konfiguracji.echo
- jest wbudowany w wydajność.help
- może korzystać z osobnej bazy danych, ale osadzenie tekstu pomocy w pliku wykonywalnym powłoki ma tę zaletę, że powoduje, że plik wykonywalny powłoki jest samodzielny.kill
- wbudowanie ma dwie zalety: oprócz identyfikatorów procesów może rozpoznać oznaczenia zadań i można go używać nawet wtedy, gdy nie ma wystarczających zasobów, aby rozpocząć osobny proces.printf
- z tego samego powodu echo
, a także w celu obsługi -v
opcji umieszczenia wyniku w zmiennej.pwd
- wbudowane oferuje dodatkową możliwość logicznego śledzenia bieżącego katalogu (pozostawiając nietknięte łącza symboliczne zamiast je rozszerzać).test
- jest wbudowanym narzędziem zwiększającym wydajność (a bash robi też magię z plikami wywoływanymi /dev/fd/…
w niektórych systemach operacyjnych).Kilka powłok oferuje znaczną liczbę dodatkowych wbudowań. Jest skrzydło , które jest powłoką zaprojektowaną jako samodzielny plik binarny do napraw awaryjnych (gdy niektóre zewnętrzne polecenia mogą nie być użyteczne). Ma wbudowane tak ls
zwane -ls
, a także inne narzędzia, takie jak -grep
i -tar
. Wbudowane funkcje Sasha mają mniej możliwości niż pełnoprawne polecenia. Zsh oferuje podobne funkcje wbudowane w module zsh / files . Nie ma ls
, ale interpretacja symboli wieloznacznych ( echo *
) i zstat
może pełnić podobną funkcję.
Myślę, że coś, czego brakuje ludziom, to złożoność ls
programu GNU w Linuksie. Porównując wielkość wykonywalny ls
do bash
i dash
muszli w moim systemie Debian, widzimy, że jest to dość duży:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
Uwzględnienie ls
tak pełnej funkcjonalności jak wersja GNU bash
zwiększyłoby rozmiar pliku wykonywalnego o 10%. Ma prawie taki sam rozmiar jak pełna dash
skorupa!
Większość wbudowanych powłok jest wybierana, ponieważ integrują się z powłoką w sposób, którego nie mogą wykonać zewnętrzne pliki wykonywalne (pytanie to wskazuje cd
, ale innym przykładem jest wersja bash kill
integracji z kontrolą zadań bash) lub ponieważ są to bardzo proste polecenia do wdrożenia, dając dużą szybkość w porównaniu do wielkości ( true
i false
są tak proste, jak to tylko możliwe).
GNU ls
ma długi cykl rozwoju, a implementacje mogą zawierać opcje dostosowywania wyświetlanych wyników. Domyślnie użycie wbudowanego ls spowoduje utratę tej funkcjonalności lub znaczne zwiększenie złożoności i wielkości powłoki.
Rób to, czego szukasz:
printf "%s\n" *
Możesz także przechowywać nazwy plików w tablicy:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Ale to nie obchodzi spacji w nazwach
Przechodzi do zmiennej i dba o spacje:
printf "%s\n" * | while read a; do echo $a; done
ls
jest to program zewnętrznyecho *
lubecho * .*
(w zależności od opcji powłoki) całkiem dobrze spisuje pliki bez rozwidlania.