execve()の制限 (Argument list too long)

そういえば先日、某所で若手に「Linuxでたくさんのファイルを一気に消したいんですがエラーが出て消せません!どうするんですか!」と質問された。フレッシュだね。よかよか。

$ rm *
-bash: /bin/rm: Argument list too long

ちょ、これ、ほんまに、全部、消して、いいの?
・・・とは聞かずに優しく教えておきました。仕事じゃないので。(そういう問題か)

$ echo * | xargs rm -r

ところで

"Argument list too long"と出ているが、何がどの辺で限界をむかえているんだろう。

長さの制限は OS によって異なり、FreeBSD では 64KB、Linux のあるディストリビューションでは 128KB、SunOS4〜Solaris は 1MB、HP-UX 10.20 までは 20KB (パッチを当てれば 2MB)、HP-UX 11.x 以降は 2MB である。この値は伝統的に ARG_MAX というマクロ定数で定義されているため、使っている UNIX の ARG_MAX を調べたい場合は /usr/include を ARG_MAX で grep するか、getconf コマンドを使って

% getconf ARG_MAX
65536

とすることで調べることができる。FreeBSD なら sysctl で

% sysctl -A kern.argmax
kern.argmax: 65536

としてもよい。なお、ARG_MAX は 4096 以上であるべき、と POSIX には規定されている。

コマンド:xargs: UNIX/Linuxの部屋

とのことだ。なるほど。execve()の制限を超えてるのね。

$ getconf ARG_MAX
131072

$ cat /proc/version
Linux version 2.6.21.7-2.fc8xen (mockbuild@xenbuilder1.fedora.redhat.com) (gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)) #1 SMP Fri Feb 15 12:39:36 EST 2008

ちなみに手元の、というかAmazon EC2で動かしているFedora8(kernel2.6.21-xen)で試してみたら、確かに128kbだった。

カーネル 2.6.23 より前の Linux では、環境変数と引き数の文字列群を格納するのに使用されるメモリは 32 ページに制限されていた (32 ページというのはカーネル定数 MAX_ARG_PAGES で定義される)。したがって、ページサイズが 4 kB のアーキテクチャでは、最大サイズは 128 kB ということになる。

http://www.linux.or.jp/JM/html/LDP_man-pages/man2/execve.2.html