「パラメータリストが長すぎます」:コマンドを変更せずにこれを処理する方法は?

「パラメータリストが長すぎます」:コマンドを変更せずにこれを処理する方法は?

このようなコマンドを実行するとls */*/*/*/*.jpgエラーが発生します。

-bash: /bin/ls: Argument list too long

私はなぜこれが起こるのか知っています。コマンド引数のスペースサイズにカーネル制限があるためです。標準的なアドバイスは、あまりにも多くの引数スペースを必要としないように使用するコマンドを変更することです(たとえば、usefindxargs)。

コマンドを変更したくない場合はどうすればよいですか?同じコマンドを引き続き使用するにはどうすればよいですか?このエラーが発生せずに「正しく動作する」ようにするにはどうすればよいですか?どのソリューションを使用できますか?

答え1

Linuxでは、コマンドパラメータの最大スペースは利用可能なスタックスペースの1/4です。したがって、解決策はスタックの空き容量を増やすことです。

ショートバージョン:次のことを実行します。

ulimit -s 65536

より長いバージョン:スタックのデフォルトの空き容量は約8192KBです。次のように空き容量を確認できます。

$ ulimit -s
8192

より大きな数字を選択し、スタックの空き容量を設定します。たとえば、スタックを最大65536KBまで許可するには、次のコマンドを実行します。

$ ulimit -s 65536

必要なサイズを決定するには、試行錯誤を受ける必要があります。ほとんどの場合、これはコマンドや計算構文などを変更する必要がない迅速で汚い解決策です。findxargsこれは他の利点があることを知っていますが)

私はこれがLinuxに限定されていると思います。他のUnixオペレーティングシステム(テストされていない)では役に立ちません。

答え2

代わりに、ls */*/*/*/*.jpg以下を試してください。

echo */*/*/*/*.jpg | xargs ls

xargs(1)システム内の最大引数の数を特定すると、標準入力が爆発し、その制限を超えない引数で指定されたコマンドラインを複数回呼び出します(最大値より低く設定することもできます)。このオプションを使用するオペレーティングシステム-n)。

たとえば、3つのパラメータ制限と5つのファイルがあるとします。この場合は2回xargs実行されますls

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

多くの場合、これは完全に適切ですが、必ずしもそうではありません。たとえば、ls(1)に依存することはできません。種類各個別のls呼び出しは指定された項目のサブセットのみをソートするため、すべての項目が正しくソートされますxargs

他の人が提案したように制限を増やすことはできますが、制限はまだ存在します。いつかJPGコレクションが再び制限を超えてしまいます。無制限に処理できるスクリプトを準備する必要があります。

答え3

これLinuxジャーナル記事4つのソリューションがあります。 4番目の解決策だけがコマンド変更を含みません。

方法#4には、コマンドラインパラメータに対してカーネルに割り当てられているページ数を手動で増やすことが含まれています。 include/linux/binfmts.h ファイルを見ると、上部付近に次の内容があります。

/*
 * MAX_ARG_PAGES defines the number of pages allocated for   arguments
 * and envelope for the new program. 32 should suffice, this gives
 * a maximum env+arg of 128kB w/4KB pages!
 */
#define MAX_ARG_PAGES 32

コマンドライン引数のみのメモリ量を増やすには、MAX_ARG_PAGESに大きな値を指定するだけです。この編集内容を保存したら、通常どおりに新しいカーネルを再コンパイルしてインストールして再起動します。

私のテストシステムでは、値を64に上げて、すべての問題を正常に解決しました。幅広いテストを経た後、移行後は何の問題も発生しませんでした。これは、64に設定してもMAX_ARG_PAGES生成できる最長のコマンドラインが256KBのシステムメモリのみを占めるため、これは完全に予想されます。これは、今日のシステムハードウェア規格に比べてあまり多くない数値です。

アプローチ#4の利点は明らかです。これで、コマンドを正常に実行すると正常に完了します。欠点も同様に明らかです。使用可能なシステムメモリ量を超えてコマンドラインで使用できるメモリ量を増やすと、システムがDOS攻撃を開始してシステムがクラッシュする可能性があります。特に、マルチユーザシステムでは、各ユーザに追加のメモリが割り当てられるため、小さな増加でさえ大きな影響を及ぼす可能性がある。したがって、常に自分の環境で幅広いテストを実行してください。これが方法#4があなたに適しているかどうかを判断する最も安全な方法です。

私はこの制限が非常に迷惑であることに同意します。

答え4

プールスペースの制限に達すると、Bashシステム呼び出しと直接的なバリエーション(引数と環境変数)が「引数リストが長すぎます」を生成します。

私が見つけたこの制限を回避する方法、処理特殊文字ファイル名(スペースなど)には、次のものを使用します。印刷機能そしてパラメータ:

printf '%s\0' */*/*/*/*.jpg | xargs -0 ls

関連情報