1) おっしゃる通り、ls
どちらが失敗しているかではありません。起動前にグロブ展開を行うシェルls
です。次のようなものを使用することで、その問題を簡単に修正できます
find . -type f -name 'GLOB' | xargs UTILITY
例えば。:
find . -type f -name '*.dat' | xargs ls -l
find
(効率のために)(通常)ファイル名をソートしないため、出力をソートすることをお勧めします。find
(ディレクトリ再帰の深さの設定、より複雑な方法でのフィルタリングなど) およびxargs
(呼び出しごとの引数の最大数、並列実行など) には、他にも多くのオプションがあります。詳しくはman
ページをご覧ください。
2)個々のファイルをどのように作成しているのかわかりません。そのため、具体的な解決策を提供するのは少し難しいですが、いくつかのアイデアがあります:
自分でファイルを作成する必要があり、ファイルの作成をジョブの最後まで遅らせることができ (たとえば、出力をバッファリングすることにより)、ファイルはアドバイザリ ロックまたはアトミック リンクなどの他のロック メカニズムをサポートするファイル システムに保存されます。 、出力を吐き出す前にロックしてからロック解除することで、さまざまなジョブを単一のファイルに多重化できます。しかし、それは多くの要件です。クラスターでは、単一のホストで実行されているすべてのジョブに対して単一のファイルでそれを実行できる可能性がありますが、そうでない場合もあります。
繰り返しになりますが、自分でファイルを作成する場合は、各行を共有ファイルにアトミックに書き込むことができます。(NFS でさえアトミックな書き込みをサポートしていますが、アトミックな追加はサポートしていません。以下を参照してください。) デマルチプレックスできるように、各行の前に一意のジョブ識別子を追加する必要があります。stdout
ただし、悲しいことに一般的な「ジョブが書き込みを行い、スケジューリング フレームワークがそれをファイルにコピーする」などの自動メカニズムを使用している場合、これは機能しません。(本質的に、この提案はMapReduce
戦略にかなり似ています。おそらくそれはあなたに利用できますか?)
他のすべてに失敗した場合は、サブディレクトリを使用できます。それぞれ千ファイルの数千のディレクトリは、数百万のファイルを持つ単一のディレクトリよりもはるかに管理しやすいです。
幸運を。
編集要求に応じて、2.2 に関する詳細:
これにはPosix I / O関数を使用する必要があります。これは、C
ライブラリがアトミック書き込みを提供していないためです。Posix では、ファイルを開くときに指定した場合、書き込み関数は常にアトミックに書き込みます。O_APPEND
(実際には、どのような場合でもアトミックに書き込みますが、指定しない場合、O_APPEND
各プロセスはファイル内の独自の位置を保持するため、互いに上書きしてしまいます。)
だからあなたがする必要があるのは:
プログラムの最初に、open
オプションを含むファイルO_WRONLY|O_CREATE|O_APPEND
. (先に言ったこととは反対に、NFS は適切に処理されない可能性があるため、これが NFS で動作することが保証されているわけではありませんO_APPEND
。NFS の新しいバージョンは、理論的には追加専用ファイルを処理できますが、おそらくそうではありません。これについては少し後で考えます。 .) おそらく常に同じファイルを使用したくないので、さまざまなジョブがさまざまな代替手段を持つように、名前のどこかに乱数を入れてください。O_CREAT
くだらないNFS実装であっても、常にアトミックです。
出力行ごとにsprintf
、行は内部バッファーに入れられ、先頭に一意の ID が付けられます。(あなたの仕事にはある種の一意の ID が必要です。それを使用してください。) [偏執的である場合は、ある種のレコード区切り文字で行を開始し、その後に残りの行のバイト数を続けます。フォーマット後にこの値を入力してください -- そのため、行は次のよう^0274:xx3A7B29992A04:<274 bytes>\n
になります^
。
write
ファイルへの行全体。戻りコードと書き込まれたバイト数を確認してください。書き込みに失敗した場合は、再試行してください。書き込みが短かった場合は、上記の「偏執的である場合」の手順に従っていただければ幸いです。もう一度やり直してください。
本当に、あなたは短い文章を書くべきではありませんが、あなたは決して知りません. 長さを書くのはとても簡単です。逆多重化はもう少し複雑ですが、必要なときにその橋を渡ることができます:)
NFS を使用する際の問題は、もう少し煩わしいものです。2.1 と同様に、最も簡単な解決策は、ファイルをローカルに書き込むか、追加を適切にサポートするクラスター ファイルシステムを使用することです。(NFSv4 では、"追加" パーミッションのみを要求でき、"書き込み" パーミッションは要求できません。これにより、他のプロセスが使用しようとしていたオフセットへの書き込みが既に管理されている場合、サーバーは書き込みを拒否します。その場合、最終的に成功するまで、ファイルの最後までシークし、書き込みを再試行する必要があります。ただし、この機能は実際には実装されていないという印象があります。間違っている可能性があります。)
ファイルシステムが追加をサポートしていない場合は、別のオプションがあります。行の長さを決定し、常にそのバイト数を書き込みます。(明らかに、選択した固定行の長さが可能な限り長い行よりも長い方が簡単ですが、シーケンス番号がある限り、複数の固定長の行を書き込むことができます。)各ジョブが次の場所に書き込むことを保証する必要があります。ジョブのジョブ番号をファイル番号とインターリーブ番号に分割し、特定のジョブのすべての行をそのインターリーブでインターリーブ数を法として、ファイル番号を含む名前のファイルに書き込むことで、さまざまなオフセットを実行できます。(これは、ジョブに順番に番号が付けられている場合に最も簡単です。) unix ファイルシステムでは -- または少なくとも、
追加をサポートしないが、アドバイザリ バイト範囲ロックをサポートする (NFSv4 はこれをサポートする) ファイルシステムを処理する別の方法は、上記の固定行長のアイデアを使用することですが、前に書き込まれようとしている範囲でロックを取得します。それを書いています。ノンブロッキング ロックを使用し、ロックを取得できない場合は、次の行オフセット倍数で再試行します。ロックを取得できる場合は、そのオフセットでファイルを読み取り、書き込む前にデータがないことを確認します。ロックを解除します。
それが役立つことを願っています。