Odkryłem, że spowodowałoby to błąd „zbyt długi argument”:
ls *.*
I to by go nie podniosło:
for file in *.*
do
echo $file
done
Dlaczego?
Odkryłem, że spowodowałoby to błąd „zbyt długi argument”:
ls *.*
I to by go nie podniosło:
for file in *.*
do
echo $file
done
Dlaczego?
Odpowiedzi:
Błąd „zbyt długi argument” jest E2BIG
wywoływany przez execve
wywołanie systemowe, jeśli całkowity rozmiar argumentów (plus środowisko, w niektórych systemach) jest zbyt duży. execve
Wezwanie jest ten, który rozpoczyna procesów zewnętrznych, a konkretnie ładuje inny plik wykonywalny (jest inna rozmowa, fork
na prowadzenie oddzielnego procesu, którego kod jest nadal z tego samego pliku wykonywalnego). for
Pętli wewnętrzna konstrukcja płaszcza tak, że nie obejmuje wywołanie execve
. Polecenie ls *.*
podnosi błąd nie po rozwinięciu globu, ale po ls
wywołaniu.
execve
kończy się błędem, E2BIG
gdy całkowity rozmiar argumentów polecenia jest większy niż ARG_MAX
limit . Możesz zobaczyć wartość tego limitu w swoim systemie za pomocą polecenia getconf ARG_MAX
. (Możliwe, że możesz przekroczyć ten limit, jeśli masz wystarczającą ilość pamięci; utrzymywanie poniżej ARG_MAX
gwarancji, które execve
będą działać, dopóki nie wystąpi niepowiązany błąd).
execve
Limit jest egzekwowany przez jądro, nakłada ograniczenia, ponieważ argumenty muszą zostać skopiowane przez pamięć jądra w jednym punkcie, a procesy użytkownika nie mogą żądać dowolnej ilości pamięci powłoki. Wewnątrz powłoki nie ma powodu, aby mieć limit, wszystko, co mieści się w pamięci wirtualnej, jest w porządku.
Przypuszczam, że w pierwszym przykładzie ls
jest wykonywana bash
przez wywołanie systemowe fork
/ exec
pair, w drugim cała praca jest wewnętrzna bash
.
exec
Wezwanie ma swoje granice, wewnętrzny roboczy bash
zamiast nie ma (albo lepiej, ma różne ograniczenia, które nie mają nic wspólnego z exec
, być może ilość dostępnej pamięci).
exec
w /usr/include/linux/limits.h
zazwyczaj zdefiniowany jako ARG_MAX
.
Ponieważ w tym przypadku ls
jest to argument, a liczba argumentów jest ograniczona.
W przypadku for
cyklu jest to tylko lista pozycji. Nie ma żadnych ograniczeń (o ile mi wiadomo).
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
/bin/bash
vs./bin/sh
(który może być linkiem do myślnika)?