CP: đối số số tệp tối đa cho tiện ích sao chép


11

Hãy xem xét rằng có vô số tệp trong / src /

cp /src/* /dst/

Có bao nhiêu tập tin cpsẽ xử lý thành công?


2
Nếu danh sách đối số quá dài (hãy nhớ, những gì * hiện đang mở rộng thành danh sách tất cả các tệp khớp với toàn cầu), bạn có thể khắc phục bằng cách sử dụng ví dụ IFS="\n" for file in /src/*; do mv "$file" /dst/; donehoặc rsync -a /src/ /dst/.
DopeGhoti

Câu trả lời:


18

Điều đó phụ thuộc rất lớn vào hệ thống và phiên bản, vào số lượng và kích thước của các đối số cũng như số lượng và kích thước của tên biến môi trường.

Theo truyền thống trên Unix, giới hạn (như được báo cáo bởi getconf ARG_MAX) ít nhiều về kích thước tích lũy của:

  • Độ dài của các chuỗi đối số (bao gồm cả kết thúc '\0')
  • Độ dài của mảng con trỏ tới các chuỗi đó, do đó, thường là 8 byte cho mỗi đối số trên hệ thống 64 bit
  • Độ dài của các chuỗi môi trường (bao gồm cả kết thúc '\0'), một chuỗi môi trường theo quy ước tương tự var=value.
  • Độ dài của mảng con trỏ tới các chuỗi đó, do đó, thường là 8 byte cho mỗi đối số trên hệ thống 64 bit

Ghi nhớ rằng cpcũng được tính là một đối số (là đối số đầu tiên).

Trên Linux, nó phụ thuộc vào phiên bản. Hành vi ở đó đã thay đổi gần đây khi nó không còn là một không gian cố định.

Kiểm tra trên Linux 3.11, getconf ARG_MAXhiện báo cáo một phần tư giới hạn được đặt trên kích thước ngăn xếp hoặc 128kiB nếu đó nhỏ hơn 512kiB).

( zshcú pháp dưới đây):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

Giới hạn đó nằm ở kích thước tích lũy của đối số và chuỗi môi trường và một số chi phí chung (tôi nghi ngờ do xem xét căn chỉnh trên ranh giới trang). Kích thước của con trỏ không được tính đến.

Tìm kiếm giới hạn, tôi nhận được:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

Kích thước tích lũy tối đa trước khi phá vỡ trong trường hợp đó là:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

Bây giờ, điều đó không có nghĩa là bạn có thể vượt qua 1 triệu đối số trống. Trên hệ thống 64 bit, 1 triệu đối số trống tạo danh sách con trỏ 8 MB, cao hơn kích thước ngăn xếp 4MiB của tôi.

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(bạn sẽ nhận thấy đó không phải là lỗi E2BIG. Tôi không chắc chắn tại thời điểm nào quá trình sẽ bị giết ở đó nếu nó nằm trong execvecuộc gọi hệ thống hoặc sau này).

Cũng lưu ý (vẫn trên Linux 3.11) rằng kích thước tối đa của một đối số hoặc chuỗi môi trường là 128kiB, bất kể kích thước của ngăn xếp.

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK

Bạn có thể chia sẻ xin vui lòng, làm thế nào bạn đến với 164686số? tức là làm thế nào bạn tính được chuỗi đó sẽ có 2097152kích thước ARG_MAX?
Sergiy Kolodyazhnyy

14

Điều đó sẽ phụ thuộc vào giá trị của ARG_MAX có thể thay đổi giữa các hệ thống. Để tìm ra giá trị cho hệ thống của bạn chạy (hiển thị kết quả trên ví dụ của tôi):

$ getconf ARG_MAX
2097152

Điều này không có gì để làm với cphoặc shell của bạn, nó là một giới hạn được áp đặt bởi kernel, nó sẽ không thực thi exec()các lệnh ( ) nếu các đối số của chúng dài hơn ARG_MAX. Vì vậy, nếu độ dài của danh sách đối số bạn đã cung cấp cplớn hơn ARG_MAX, cplệnh sẽ hoàn toàn không chạy.

Để trả lời câu hỏi chính của bạn sau đó, cpsẽ xử lý không có tệp nào vì nó sẽ không bao giờ được thực thi với quá nhiều đối số. Tôi cũng nên đề cập rằng điều này không phụ thuộc vào số lượng đối số mà phụ thuộc vào độ dài của chúng. Bạn có thể hình dung có cùng một vấn đề với rất ít tên tệp rất dài.


Cách khắc phục các lỗi này là chạy lệnh của bạn trong một vòng lặp:

for file in /src/*; do cp "$file" /dst/; done

Điều này có nghĩa là các ngôn ngữ cấp thấp hơn như Ccó thể có vấn đề với ARG_MAX và tên tệp thực sự dài?
Harold Fischer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.