在使用并行选项时,如何将多个子命令传递给xargs



我试图写一个bash脚本来处理一个大的目录树和rsync,在多个流。根据对该网站的其他研究,我构建了以下内容。假设命令是运行的:

program.sh/input/location/output/location $threads

脚本中的关键行是

cd $1; find . -depth ( -type d -printf ""%p/"n" ) | xargs -n1 -P$3 -I% rsync -lptgoDds --delete --backup --backup-dir=$INCREMENTALS/$DATE/$1 % $2/%

上面的想法是找到某一点上的所有目录,然后将它们传递给并行的rsync命令实例,以将数据从$1复制到$2。

我遇到的问题是rsync可能必须创建嵌套文件夹,这些文件夹还不存在,这取决于输入是如何解析的。(至少我认为这是我所看到的错误的原因)。为了解决这个问题,我认为我可以在rsync中发出两个命令。第一个命令将创建目录,第二个命令将启动rsync。

像这样:

cd $1; find . -depth ( -type d -printf ""%p/"n" ) | xargs -n1 -P$3 -I% 'mkdir -p %;rsync -lptgoDdsv --delete % $2/%;'

但这似乎也不起作用。

所以在玩了一段时间后,我正在寻求帮助。: -)

不能像这样将带单引号的复杂命令传递给xargs。但是你可以把它传递给sh,再传递给xargs

cd $1; find . -depth ( -type d -printf ""%p/"n" ) | xargs -n1 -P$3 -I% sh -c 'mkdir -p %;rsync -lptgoDdsv --delete % $2/%;'

(我没有办法测试这个。它可能还需要一些调整

看起来GNU Parallel http://www.gnu.org/software/parallel/man.html#example__parallelizing_rsync的例子非常接近你想要的:

cd src-dir; find . -type f -size +100000 | parallel -v ssh fooserver mkdir -p /dest-dir/{//};rsync -Havessh {} fooserver:/dest-dir/{}

应该是这样的:

cd $1; find . -depth -type d | parallel -P$3 mkdir -p $INCREMENTALS/$DATE/$1 $2/{}; rsync -lptgoDds --delete --backup --backup-dir=$INCREMENTALS/$DATE/$1 {} $2/{}

如果GNU Parallel没有为您的系统打包,这应该在10秒内安装它:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

要了解更多:观看介绍视频的快速介绍:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

遍历教程(man parallel_tutorial)。命令行我会爱你的。

只是回来重新发布我认为的答案。我必须使用shell调用来完成我需要做的事情,经过大量的尝试和错误之后,我发现答案非常简单,将字段传递给子shell。通过导出它们,子shell就可以使用它们,这就像一个魔法。这是我当前的脚本。

#!/bin/bash
set -x
export INCREMENTALS="/var/backup/data"
export DATE=`date +%F`
export SRCDIR=$1
export TARGETDIR=$2
export THREADS=$3

cd $SRCDIR; find . -type d -print0 | xargs -0 -n1 -P$THREADS -I {} sh -c 'echo $TARGETDIR/"{}"; mkdir -p $TARGETDIR/"{}"; rsync -lptgoDdXvz --delete --backup --backup-dir=$INCREMENTALS/$DATE/.$SRCDIR "{}"/ $TARGETDIR/"{}"'

要运行脚本,使用以下顺序:

rsync.sh /from/dir /to/dir 20

前两个参数很明显,"20"是你想要调用的rsync线程数。

所以这样你就把许多并行rsync推到耗尽机器的地步。我发现的唯一问题是,如果存在包含数千个文件的目录,那么并行性就会崩溃,因为所有其他目录都完成了,而您只能在最长的目录后面等待。我正在想办法在第二轮中采用更多的喷雾方法。

我现在唯一的其他问题是我的内存消耗随着时间的推移而增加。我有一种有趣的感觉,有一个泄漏,这与我的脚本无关,但我担心我可能有一些无界元素在这导致不断增加的内存使用。还有另一个问题要解决,与这个无关。

net-net的答案是"导出"函数,然后子shell正确地看到内容,它工作得很好。

最新更新