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 函数,因为,afaik,该C
库不提供原子写入。在 Posix 中,write函数总是以原子方式写入,前提是您O_APPEND
在打开文件时指定。(实际上,它在任何情况下都以原子方式写入,但如果您未指定,O_APPEND
则每个进程都会在文件中保留自己的位置,因此它们最终会相互覆盖。)
所以你需要做的是:
在程序的开头,open
一个带有 options 的文件O_WRONLY|O_CREATE|O_APPEND
。(与我之前所说的相反,这不能保证在 NFS 上工作,因为 NFS 可能无法O_APPEND
正确处理。较新版本的 NFS 理论上可以处理仅附加文件,但它们可能不会。稍后对此进行一些思考.) 您可能不想总是使用同一个文件,所以在其名称中添加一个随机数,以便您的各种工作有多种选择。O_CREAT
总是原子的,afaik,即使是糟糕的 NFS 实现。
对于每个输出行,sprintf
该行到一个内部缓冲区,在开头放置一个唯一的 id。(你的工作必须有某种唯一的 id;只要使用它。)[如果你偏执,用某种记录分隔符开始该行,然后是剩余行中的字节数——你必须在格式化后输入这个值——所以该行看起来像hex 01 或类似的东西^0274:xx3A7B29992A04:<274 bytes>\n
在哪里。]^
write
文件的整行。检查返回码和写入的字节数。如果写入失败,请重试。如果写的很短,希望你遵循上面的“如果你是偏执狂”的说明,也可以再试一次。
真的,你不应该写短文,但你永远不知道。写长度很简单;多路分解有点复杂,但你可以在需要时跨过那座桥:)
使用 NFS 的问题有点烦人。与 2.1 一样,最简单的解决方案是尝试在本地写入文件,或者使用一些正确支持附加的集群文件系统。(NFSv4 允许您仅请求“附加”权限而不是“写入”权限,如果其他进程已经设法写入您将要使用的偏移量,这将导致服务器拒绝写入。在这种情况下,您'd需要寻找到文件的末尾并再次尝试写入,直到最终成功。但是,我的印象是这个功能实际上并没有实现。我可能是错的。)
如果文件系统不支持追加,您将有另一种选择:决定行长,并始终写入该字节数。(显然,如果所选的固定行长度比可能的最长行长,则更容易,但只要它们具有序列号,就可以编写多个固定长度的行。)您需要保证每个作业都写入不同的偏移量,您可以通过将作业的作业编号分为文件编号和交错编号,并将特定作业的交错处的所有行以交错数取模,写入名称包含文件编号的文件中。(如果作业按顺序编号,这是最简单的。)可以在文件末尾之外写入,因为 unix 文件系统将 - 或至少,
处理不支持追加但支持建议字节范围锁定(NFSv4 支持此)的文件系统的另一种方法是使用固定行长度的想法,如上所述,但在之前要写入的范围上获得锁定写它。使用非阻塞锁,如果无法获得锁,则在下一个行偏移倍数处重试。如果能获得锁,则读取该偏移处的文件,在写入之前验证它没有数据;然后释放锁。
希望有帮助。