web-dev-qa-db-ja.com

「引数リストが長すぎます」:コマンドを変更せずに、どのように対処しますか?

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

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

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

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

20
D.W.

Linuxでは、コマンド引数の最大スペースは、使用可能なスタックスペースの1/4です。したがって、解決策は、スタックに使用できるスペースの量を増やすことです。

ショートバージョン:次のようなものを実行します

ulimit -s 65536

長いバージョン:スタックに使用できるデフォルトの容量は8192 KBのようなものです。次のように、使用可能なスペースの量を確認できます。

$ ulimit -s
8192

より大きい数を選択し、スタックに使用可能なスペースの量を設定します。たとえば、スタックに最大65536 KBを許可する場合は、次のコマンドを実行します。

$ ulimit -s 65536

試行錯誤を使用して、これがどれほど大きい必要があるかを試してみる必要があるかもしれません。多くの場合、これはコマンドを変更してfindxargsなどの構文を計算する必要をなくす、簡単で汚れたソリューションです(ただし、そうすることの他の利点)。

これはLinux固有のものだと思います。他のUnixオペレーティングシステム(テストされていません)ではおそらく役に立たないと思います。

29
D.W.

これ Linux Journal記事 は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に上げることですべての問題を解決することができました。広範なテストを行った後、切り替え以降、1つの問題を経験していません。 MAX_ARG_PAGES 64に設定すると、生成できる最長のコマンドラインは256KBのシステムメモリしか占有しません。今日のシステムハードウェア標準ではそれほど多くありません。

方法#4の利点は明らかです。これで、通常どおりにコマンドを実行でき、正常に完了します。欠点も同様に明らかです。コマンドラインで利用可能なメモリの量を、利用可能なシステムメモリの量を超えて増やすと、D.O.S。自分のシステムを攻撃してクラッシュさせる。特にマルチユーザーシステムでは、すべてのユーザーに追加のメモリが割り当てられるため、わずかな増加でも大きな影響を与える可能性があります。したがって、方法#4が実行可能なオプションかどうかを判断する最も安全な方法であるため、常に自分の環境で広範囲にテストしてください。

私はその制限が深刻な迷惑であることに同意します。

3

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

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

xargs(1)は、システム上の引数の最大数を知っており、その標準入力を分割して、指定されたコマンドラインを複数回呼び出し、その制限よりも多くの引数を使用しません(それより低く設定することもできます) -nオプションを使用したOSの最大値よりも大きい)。

たとえば、制限が3つの引数であり、5つのファイルがあるとします。その場合、xargslsを2回実行します。

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

多くの場合、これは完全に適していますが、常にではありません-たとえば、ls(1)sortingすべてのエントリに適切に依存することはできません。それぞれのls- invocationはサブセットのみをソートするためですxargsによって与えられたエントリの数。

他の人が提案するように制限を引き上げることはできますが、それでも制限はあります-そしていつか、JPGコレクションが再びそれを超えてしまいます。無限数を処理するようにスクリプトを準備する必要があります...

3
Mikhail T.