“引数リストが長すぎます”:コマンドを変更せずに対処するにはどうすればよいですか?

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

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

これが発生する理由はわかっています。これは、コマンドへの引数用のスペースの量にカーネル制限があるためです。標準的なアドバイスは、引数にそれほど多くのスペースを必要としないように、使用するコマンドを変更することです(たとえば、findおよびxargsを使用します)。

コマンドを変更したくない場合はどうすればよいですか?同じコマンドを使い続けたい場合はどうすればよいですか?このエラーが発生せずに「正常に動作」させるにはどうすればよいですか?どのような解決策がありますか?

コメント

  • 参考資料:バッシュFAQ95 。コマンドを変更せずに'再コンパイルして引数リストの最大サイズを増やすか、ディレクトリ構造を変更してファイル数を減らす以外にできることはあまりありません。
  • @ jw013 Linuxカーネルのバージョンに基づいて、引数リストを増やすことができる場合があります。変更の詳細については、 unix.stackexchange.com/a/45161/8979 を参照してください。最近のシステム。
  • @UlrichDangel、うん、それは可能です!私の答えを見てください;私の答えはそれを行う方法を示しています(Lでinux、最近の十分なカーネルを使用)。

回答

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

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

ulimit -s 65536 

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

$ ulimit -s 8192 

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

$ ulimit -s 65536 

必要な大きさを試してみる必要がある場合があります。試行錯誤を繰り返します。多くの場合、これは、コマンドを変更してfindxargsなど(そうすることには他にも利点があることはわかっていますが)

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

コメント

  • このように動作したことを確認できます:$ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • これは、ulimit -s unlimitedを使用してスタックサイズを無制限にするとコマンドラインサイズが無制限でもありますか?

回答

ls */*/*/*/*.jpgの代わりに、試してみてください:

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

xargs(1)は、システム上の引数の最大数を認識しており、標準入力を分割して、指定されたコマンドラインを複数回呼び出し、その制限を超える引数はありません(-nオプション)。

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

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

これは完全に適していることがよくありますが、常にそうとは限りません。たとえば、できません。 ls-呼び出しを個別に行うため、すべてのエントリをls(1)並べ替えする必要があります。与えられたエントリのサブセットのみをxargsで並べ替えます。

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

コメント

  • アイデアをありがとう!これは悪い回避策ではありません。 2つの注意点:1。これは、名前にスペースが含まれているディレクトリとファイル名で破損するため、'は完全な代替ではありません。 2. Argument list too longでも同じ問題が発生しますが、ls<ではなくechoで発生します。 / div>、echoがシェルの組み込みコマンドではないシェルで? (おそらく、'はほとんどのシェルで問題にならないので、'は無関係かもしれません。)
  • はい、ファイル名の特殊文字が問題になります。最善の策は、find-print0述語とともに使用し、その出力をxargs -0オプション付き。echoはシェルに組み込まれており、exec(3)のコマンドライン制限の影響を受けません。
  • これは、lsのように、最後のパラメーターとして変数引数を期待するコマンドで機能しますが、mv多くのファイルを1つのディレクトリにmv * destdir*で"引数が多すぎる"エラーが発生した場合、' xargsを作成して、最初のパスをmvに渡すようにしますか、それともできますか?
  • システムのxargsのマニュアルページを確認します。たとえば、FreeBSDでは-Jが役立ちます。このタスクであなた。 OSでこれを行う方法がない場合は、'引数を並べ替えるカスタムスクリプトを作成する必要があります。 destdir=$1; shift; mv "$@" "$destdir"のようなもの。次に、この新しいスクリプトをxargsに渡します:.... | xargs newscript $destdir

回答

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

制限が非常に煩わしいことに同意します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です