使用Bash中的xargs将命令输出发送到唯一文件

时间:2016-08-08 16:17:11

标签: linux xargs

我试图在固定数量的处理器上动态运行许多进程。我想将输出打印到每个进程的唯一文件,但是xargs没有使用就地文件名为每个进程创建单独的文件存在一些问题。

Bash脚本调用Csh脚本,如下所示:

$ cat temp | xargs -P 8 % csh '%'.csh >& '%'.log

其中temp是csh命令名的文本文件。

我的问题是xargs按字面意思取%.log并在进程写入时不断覆盖文件,而不是根据需要单独.log个文件。

我将此脚本作为$ bash run.bash &

运行

2 个答案:

答案 0 :(得分:1)

通常,使用字符串替换代替代码是一个坏主意 - 在您的情况下,如果您有一个带有恶意名称的脚本,该名称可用于运行任意命令。 (当然,你正在执行脚本,但同样适用于你纯粹处理数据和输出文件名的情况 - 因此最好养成强大方法的习惯)。

将名称​​作为参数传递给脚本,而不是将它们替换为脚本(如果您通过添加修复其用法,xargs将会这样做-I-J参数:

# best-practice approach: run a completely fixed shell script, passing arguments on
# its command line.
xargs -P 8 -n 1 \
  sh -c 'for x; do csh "${x}.csh" >"${x}.log" 2>&1; done' _

你会注意到有一个sh -c实例被调用:这是必需的,因为xargs本身不理解shell操作,例如重定向;如果你想要执行重定向,你需要一个shell来完成它。

现在,让我们再详细说明原始代码的行为原因:

xargs -P 8 % csh '%'.csh >& '%'.log

... 首先执行重定向到%.log然后运行命令

xargs -P 8 % csh '%'.csh

xargs没有机会替换%.log字符串,因为在 xargs命令运行之前,重定向是由封闭的shell 执行的

答案 1 :(得分:1)

使用GNU Parallel看起来像这样:

cat temp | parallel -P 8 'csh {}.csh >& {}.log'

如果您有8个核心,您甚至可以这样做:

cat temp | parallel 'csh {}.csh >& {}.log'

GNU Parallel引用{},以便不会执行恶意输入。