linux - “參數列表太長”限制是否適用於shell內置函數?



bash unix (2)

我瀏覽了Stack Overflow上的很多 posts 以及關於 argument list too long 的一些相關社區 argument list too long 主題,我似乎沒有清楚地知道長度限制是否適用於shell內置 argument list too long

假設我想通過標準輸入將一個非常長的字符串傳遞給命令:

string="a very long list of words ..."

我能說......麼:

# not using double quotes around $string is deliberate
printf '%s\n' $string | cmd ...

要么

cmd <<< $string

甚至將它傳遞給 xargs

printf '%s\n' $string | xargs cmd ...

有人可以澄清一下嗎?


Answer #1

我似乎沒有計算長度限制是否適用於shell內置函數。

可能不是,但你應該檢查你的特定版本的 bash 的源代碼(因為它是免費軟件)。 但是,顯然有一些 - 更大的限制(特別是因為在 bash 完成的一些 malloc 可能會失敗),但是你會得到另一個錯誤消息或行為。

AFAIK,參數列表太長錯誤由 execve(2) 給出了 E2BIG 失敗,而bash的內置函數沒有 fork 然後 execve (就像命令調用外部程序那樣)。

在實踐中, E2BIG 可能會出現幾十萬字節(確切的限制取決於內核和系統),但我想內置可以使用幾十兆字節(在今天的桌面上)。 但是YMMV(因為你可以使用 ulimit 讓你的shell做一些 setrlimit(2) ......)。 我不建議通過shell內置處理千兆字節的數據。

順便說一句, xargs(1) 可能會有所幫助,您甚至可以通過重新編譯內核來提高限制(對於 E2BIG )(在最近的內核中也可以通過其他方式)。 幾年前,這是我重新編譯內核的強烈動機。


Answer #2

在bash中,操作系統對命令行長度的強制限制導致錯誤 argument list too long ,不適用於shell builtins。

execve() 系統調用返回錯誤代碼 E2BIG 時會觸發此錯誤。 調用內置函數時不涉及 execve() 調用,因此無法發生錯誤。

因此,你提出的兩個操作都是安全的: cmd <<< "$string"$string 寫入一個臨時文件,它不要求它作為argv元素傳遞(或者一個環境變量,它存儲在同一個文件中)預留空間池); 並且 printf '%s\n' "$cmd" 發生在shell內部,除非shell的配置已經被修改,就像 enable -n printf ,以使用外部 printf 實現。





command-line-arguments