ls
を使用して/usr/
内のすべてのファイルを一覧表示したいと思います。 ls
を直接呼び出すのではなく、xargs
を介して呼び出します。さらに、xargs
パラメーター-L
および-P
を使用して、すべてのコアを利用しています。
find /usr/ -type f -print0 | xargs -0 -L16 -P4 ls -lAd | sort -k9 > /tmp/aaa
上記のコマンドは期待どおりに機能します。それは素晴らしい出力を生成します。ただし、行数-L
パラメーターを16から64に増やすと、次のようになります。
find /usr/ -type f -print0 | xargs -0 -L64 -P4 ls -lAd | sort -k9 > /tmp/bbb
結果の出力はすべて文字化けします。つまり、出力は新しい行で開始されなくなり、新しい行は「前の」行の途中で開始され、すべて混同されます。
-rw-r--r-- 1 root root 5455 Nov 16 2010 /usr/shareonts/X11/encodings/armscii-8.enc.gz
-rw-r--r-- 1 root root 1285 May 29 2016-rw-r--r-- 1 root root 6205 May 29 2016 /usr/include/arpa/nameser_compat.h
-rw-r--r-- 1 root root 0 Apr 17 20-rw-r--r-- 1 root root 933 Apr 16 2012 /usr/share/icons/nuoveXT2/16x16/actions/address-book-new.png
-rw-r--r-- 1 root root 53651 Jun 17 2012-rw-r--r-- 1 root root 7117 May 29 2016 /usr/include/dlfcn.h
-rw-r--r-- 1 root root 311 Jun 9 2015-rw-r--r-- 1 root root 1700 Jun 9 2015 /usr/share/cups/templates/de/add-printer.tmpl
-rw-r--r-- 1 root root 5157 M1 root root 10620 Jun 14 2012 /usr/lib/Perl5/Tk/pTk/tkIntXlibDecls.m
-rw-r--r-- 1 root -rwxr-xr-x 1 root root 1829 Jan 22 2013 /usr/lib/emacsen-common/packages/install/dictionaries-common
-rw-r--r-- 1 root r-rw-r--r-- 1 root root 1890 Jun 2 2012 /usr/share/Perl5/Date/Manip/TZ/afaddi00.pm
-rw-r--r-- 1 root root 1104 Jul-rw-r--r-- 1 root root 10268 Jul 27 15:58 /usr/share/Perl/5.14.2/B/Debug.pm
-rw-r--r-- 1 root root 725 Apr 1-rw-r--r-- 1 root root 883 Apr 1 2012 /usr/share/icons/gnome/16x16/actions/address-book-new.png
面白いことに、それは-L64
以上を使用している場合にのみ発生します。 -L16
ではこの問題は発生しません。
誰かがここで何が起こっているのか説明できますか?
これは、パイプへの書き込みと関係があります。 -L16
を使用すると、16個のファイルごとに1つのプロセスを実行します。これにより、ファイル名の長さにもよりますが、約1,000文字が生成されます。 -L64
を使用すると、約4,000人になります。 ls
プログラムは、ほぼ確実にstdioライブラリを使用し、ほぼ確実に、書き込み呼び出しの数を減らすために出力に4kBバッファを使用します。
したがって、findはファイル名のロードを生成し、(-L64の場合)xargsはそれらを64のバンドルに切り刻み、4つのls
プロセスを起動してそれらを処理します。各ls
は、最初の4kの出力を生成し、それをパイプに書き込んでソートします。この4kは通常not改行で終わることに注意してください。つまり、3番目のls
が最初の4kBを最初に準備し、それが終了するとします。
lrwxrwxrwx 1 root root 6 Oct 21 2013 bzegrep -> bzgrep
-rwxr-xr-x 1 root root 4877 Oct 21 2013 bzexe
lrwxrwxrwx 1 root root 6 Oct 2
次に、最初のlsは何かを出力します。
total 123459
その場合、ソートする入力にはlrwxrwxrwx 1 root root 6 Oct 2total 123459
が含まれます。
-L16
の場合、ls
プロセスは(通常)一度に結果の完全なセットのみを出力します。
もちろん、この場合、xargsとlsを使用して時間とリソースを浪費しているだけなので、追加のプログラムを実行して情報を再度検出するのではなく、find
にすでに持っている情報を出力させる必要があります。
GNU Parallelは、ミキシングの問題(実行時間40秒)を正確に解決するために構築されました。
find /usr/ -type f -print0 | parallel -0 -L64 -P4 ls -lAd | sort -k9 > /tmp/bbb
コアの数(実行時間40秒)も検出できます。
find /usr/ -type f -print0 | parallel -0 -L64 ls -lAd | sort -k9 > /tmp/bbb
そして、入力を均等に分割します(実行時間24秒):
find /usr/ -type f -print0 | parallel -0 -X ls -lAd | sort -k9 > /tmp/bbb