Bash

Shell內置printf行限制?

  • May 20, 2019

/usr/bin/printfutil 參數列表長度限制為 shell 的最大命令行長度(即*,* getconf ARG_MAX在我的系統上為2097152);例子:

# try using a list that's way too long
/usr/bin/printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1

輸出:

bash: /usr/bin/printf: Argument list too long

今天我被告知shell builtin printf沒有這個限制。測試:

printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1

輸出:

4194304

問題:

  1. 略讀man bash dash一下似乎並沒有說明builtin printf的這種優勢。記錄在哪裡?
  2. builtin printf s ( eg )是否bash有一個以字元為單位的參數列表最大長度,如果有,該長度是多少?

/usr/bin/printf util 參數列表長度限制為 shell 的最大命令行長度(即 getconf ARG_MAX,在我的系統上為 2097152);例子:

這不是shell的限制,而是作業系統(Linux 核心)的限制,特別是其execve(2)係統呼叫的限制,並且是由命令行參數和環境變數傳遞給已啟動程序的過時方式引起的。

(請注意,該限制還包括環境變數!)。

瀏覽一下 man bash dash 似乎並沒有說明內置 printf 的這種優勢。它記錄在哪裡?內置 printfs 是否有參數列表長度(例如 bash),如果有,它是什麼?

由於 shell 內置程序沒有通過execve(2),因此它們不必有任何限制。現代外殼通常不使用固定大小的緩衝區等,因此限制通常由可用記憶體量和虛擬地址空間的佈局強加——即對於所有意圖和目的來說都是無限的。

提倡使用任何特定實用程序並不是手冊的真正職責。它應該主要描述可用的內置實用程序。

使用內置實用程序相對於外部實用程序的優勢主要在於速度和擴展功能的可用性(例如printfbash可以使用 直接寫入變數-v varname,這是外部printf無法做到的)。

與執行內置實用程序相比,執行外部實用程序很慢,特別是如果經常在循環中執行,而且,正如您所注意到的,它們還允許更長的參數列表(這不是只有內置printf允許的,但所有內置實用程序)。

內置printf實用程序的參數列表的長度受程序本身bash的資源限制的限制。bash在某些系統上,這甚至可能意味著您可以使用大部分可用 RAM 來建構其命令行參數列表。

您可以從中找到這些不同資訊的文件是

  • bash原始碼,您將在其中看到參數列表printf是動態分配的鍊錶,並且它用於execve()執行printf(這是在執行外部實用程序時限制參數列表長度的原因)。

一個沒有printf內置實用程序的shell範例是OpenBSD 的 shell。該實用程序也可以在使用時禁用ksh``bash``enable -n printf

引用自:https://unix.stackexchange.com/questions/519789