web-dev-qa-db-ja.com

シェル組み込みの `printf`行制限?

/usr/bin/printf util引数リストの長さは、シェルのコマンドラインの最大長(iegetconf 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

今日 私は知らされています そのシェルbuiltinprintfsにはその制限はありません。テスト:

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

出力:

4194304

質問:

  1. man bash dashの概要は、builtinprintfのこの利点についてあまり語っていないようです。 はどこにありますか文書化されていますか?

  2. 実行builtinprintfs(egbash)引数リストの最大長を文字数で指定します。その場合、その長さはいくつですか?

6
agc

特定のユーティリティの使用を提唱するのは、マニュアルの仕事ではありません。利用可能な組み込みユーティリティを主に記述する必要があります。

外部のユーティリティよりも組み込みのユーティリティを使用する利点は、主に速度と拡張機能の可用性です(たとえば、printfbashは、_-v varname_、これは外部printfが行うことはできませんでした)。

外部ユーティリティの実行は、組み込みユーティリティを実行する場合に比べて遅くなります。ループ、そしてあなたが気づいたように、それらはより長い引数リストも許可します(これは組み込みprintfだけが許可するものではなく、すべての組み込みユーティリティです)。

printfの組み込みbashユーティリティへの引数リストの長さは、bashプロセス自体のリソース制限によって制限されます。一部のシステムでは、これは、使用可能なほとんどのRAMを使用して、コマンドライン引数リストを作成できることを意味する場合もあります。

これらのさまざまな情報を見つけるためのドキュメントは、

  • bashソースコードprintf の引数リストが動的に割り当てられたリンクリストであることがわかります。 notexecve() を使用してprintfを実行します(これにより、外部ユーティリティ実行時の引数リスト)。

組み込みユーティリティのprintfではないシェルの例は、OpenBSDのkshシェルです。ユーティリティは、_enable -n printf_を使用してbashdisabledにすることもできます。

14
Kusalananda

/ usr/bin/printf util引数リストの長さは、シェルのコマンドラインの最大長(つまり、私のシステムではgetconf ARG_MAX、2097152)に制限されています。例:

これはShellの制限ではありませんが、(Linuxカーネルの)OSの制限、特にexecve(2) syscallの制限であり、コマンドが古くなった方法によって引き起こされます行引数と環境変数は、開始されたプログラムに渡されます。

(その制限には環境変数も含まれることに注意してください!).

Man bash dashの概要は、組み込みのprintfのこの利点についてあまり語っていないようです。どこに記載されていますか?組み込みのprintfには引数リストの長さ(たとえば、bash)がありますか?ある場合、それは何ですか?

Shellビルトインはexecve(2)を経由しないため、そのような制限はありません。モダンシェルは通常、固定サイズのバッファーなどを使用しないため、制限は通常、使用可能なメモリの量と仮想アドレス空間のレイアウトによって課されます。つまり、すべての意図と目的に対して無制限です。

2
mosvy

POSIX標準では、シェルを行制限なしで実装する必要があります。

したがって、これはシェルが文書化しない自然さです。

ところで、テキストファイルはLINE_MAXより長い行を持たないファイルなので、この事実のため、シェルスクリプトはテキストファイルではない可能性があります;-)

0
schily