Tôi thấy rằng điều này sẽ gây ra lỗi "đối số quá dài":
ls *.*
Và điều này sẽ không nâng cao nó:
for file in *.*
do
echo $file
done
Tại sao?
Tôi thấy rằng điều này sẽ gây ra lỗi "đối số quá dài":
ls *.*
Và điều này sẽ không nâng cao nó:
for file in *.*
do
echo $file
done
Tại sao?
Câu trả lời:
Đối số trên mạng quá dài Lỗi lỗi được E2BIG
đưa ra bởi lệnh execve
gọi hệ thống nếu tổng kích thước của các đối số (cộng với môi trường, trên một số hệ thống) quá lớn. Cuộc execve
gọi này là cuộc gọi bắt đầu các quy trình bên ngoài, cụ thể tải một tệp thực thi khác (có một cuộc gọi khác fork
, để chạy một quy trình riêng có mã vẫn từ cùng một tệp thực thi). Các for
vòng lặp là một cấu trúc vỏ nội bộ, vì vậy nó không liên quan đến gọi execve
. Lệnh ls *.*
tăng lỗi không phải khi toàn cầu được mở rộng mà ls
là khi được gọi.
execve
không thành công với lỗi E2BIG
khi tổng kích thước của các đối số cho lệnh lớn hơn ARG_MAX
giới hạn . Bạn có thể thấy giá trị của giới hạn này trên hệ thống của bạn bằng lệnh getconf ARG_MAX
. (Có thể là bạn có thể vượt quá giới hạn này nếu bạn có đủ bộ nhớ; giữ dưới sự ARG_MAX
đảm bảo execve
sẽ hoạt động miễn là không xảy ra lỗi không liên quan.)
execve
Giới hạn được thực thi bởi kernel, nó đặt giới hạn vì các đối số cần được sao chép qua bộ nhớ kernel tại một điểm và các quy trình người dùng không thể được phép yêu cầu số lượng bộ nhớ shell tùy ý. Bên trong lớp vỏ, không có lý do gì để có bất kỳ giới hạn nào, bất cứ điều gì phù hợp với bộ nhớ ảo đều ổn.
Tôi giả sử rằng trong ví dụ đầu tiên ls
được thực hiện bash
thông qua một cuộc gọi hệ thống fork
/ exec
cặp, trong ví dụ thứ hai, tất cả các công việc là nội bộ bash
.
Cuộc exec
gọi có giới hạn, bash
thay vào đó , công việc nội bộ không có (hoặc tốt hơn, có các giới hạn khác nhau không liên quan gì exec
, có lẽ là dung lượng bộ nhớ khả dụng).
exec
trong /usr/include/linux/limits.h
thường, định nghĩa là ARG_MAX
.
Bởi vì trong trường hợp của ls
nó là một đối số và số lượng đối số bị hạn chế.
Trong trường hợp của for
chu kỳ, nó chỉ là một danh sách các mục. Không có giới hạn (theo như tôi biết) cho điều đó.
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
/bin/bash
so với/bin/sh
(mà có lẽ là một liên kết đến dash)?