通过 SSH 进入远程机器,运行 find 命令,然后将 find 的结果 rsync 回本地机器?

通过 SSH 进入远程机器,运行 find 命令,然后将 find 的结果 rsync 回本地机器?

基本上就是标题。

以下是我迄今为止取得的成功:

A)这成功找到了我需要的文件并将其显示在本地机器的终端上:

ssh remoteuser@remotemachine find /home/remoteuser/exampledirectory/ -type f -name 'examplefile*' | xargs echo

B)这成功地将所需的文件从远程机器同步到我的本地机器:

rsync -avzhe ssh --progress remoteuser@remotemachine:/home/remoteuser/exampledirectory/examplefile123.tar.gz /home/localuser/examplelocaldirectory

当我与它交互时,这两个命令工作正常;即我可以看到 find 的输出,然后手动运行第二个命令,但我正在努力将这两个概念绑定在一起作为单个命令,以便可以一次运行(因此可以通过 cronjob 自动运行)。换句话说,我需要通过 ssh 进入远程计算机,找到所需的文件,然后将 find 的结果 rysync 回我的本地计算机,所有操作一次性完成。

我可以使用私钥无密码从本地计算机访问远程计算机。我没有私钥无密码从远程计算机访问本地计算机,但如果有必要,可能可以设置它。不过,我想知道是否有办法完全从本地计算机执行此操作。

答案1

查找文件

这成功找到了文件

否。仅限您的第一个命令幸运的是找到文件。它几乎没有问题。你很幸运它给了你一个有用的输出。

在您的手动方法中,| xargs echo这几乎是无操作的。几乎,因为它可能会引入歧义。如果只有一个匹配项并且其名称在此上下文中不麻烦,则这可能不是问题。我不会解释“在此上下文中麻烦”是什么意思,因为即使| xargs echo完全没问题,您的原始第一个命令无论如何在没有它的情况下仍会起作用。

您的ssh命令本身就存在一些缺陷。这是您的命令,其中没有不必要的内容xargs

ssh remoteuser@remotemachine find /home/remoteuser/exampledirectory/ -type f -name 'examplefile*'

引用很好examplefile*,但还不够。引号阻止本地 shell 进行通配。然后ssh识别第一个看起来像要在远程端运行的命令的操作数,并从中构建实际命令后面的每个操作数。在你的情况下,这些操作数是、find/home/remoteuser/exampledirectory/-typef。最后一个是-nameexamplefile*没有引号,因为引号被本地 shell “使用”。实际上,由远程sshshell 构建并运行的远程命令是

find /home/remoteuser/exampledirectory/ -type f -name examplefile*

这会触发远程端的通配符。在某些情况下,这可能会给你带来错误或意外结果(请参阅)。

一个有趣的场景。如果examplefile*通过在远程端进行通配符扩展为examplefile123.tar.gz(因为这样的文件恰好在当前工作目录中并且是唯一匹配的),-name主服务器将获得这个精确的字符串,而不是您输入的模式,并且整个搜索将限于这个精确的文件名。下面我介绍的命令没有这样的缺陷,-name肯定会获得模式。根据远程端的文件,我的命令可能会比你的命令找到更多的文件。

这是正确的命令:

ssh remoteuser@remotemachine 'find /home/remoteuser/exampledirectory/ -type f -name "examplefile*"'

单引号包含发往远程端的整个代码。双引号将保留,并防止在远程端进行匹配。

您可以将结果存储在本地的文件中,如下所示:

ssh remoteuser@remotemachine 'find /home/remoteuser/exampledirectory/ -type f -name "examplefile*"' > filelist

将结果传递给rsync

有这样一个问题:如何rsync仅显示特定的文件列表?最好的答案建议--files-from。这是man 1 rsync说:

--files-from=FILE
使用此选项允许您指定要传输的确切文件列表(从指定文件FILE-标准输入读取)。[…]

请阅读手册的整个相关片段,特别是关于隐含的内容-R

--relative( )选项-R是隐含的,它保留为文件中的每一项指定的路径信息(如果您想关闭它,请使用--no-relative或)。--no-R

运行上面提供的最后一条命令后,您必须filelist使用 with --files-from。示例命令:

rsync -avzhe ssh --progress --files-from=filelist --no-relative remoteuser@remotemachine:/ /home/localuser/examplelocaldirectory

在本地路径上将像

/home/localuser/examplelocaldirectory/examplefile123.tar.gz

如果没有,--no-relative你会得到(在本地)像这样的路径

/home/localuser/examplelocaldirectory/home/remoteuser/exampledirectory/examplefile123.tar.gz

注意我使用了/作为源(远程)路径。这是因为您为 指定了绝对路径find,因此 中的所有路径filelist都是绝对路径;但rsync会将它们视为相对于您指定的目录。因此,该工具应从 (远程) 开始/以获取正确的对象。

但是如果你使用,find ./exampledirectory/ …那么rsync应该给出remoteuser@remotemachine:.(或只是remoteuser@remotemachine:),因为中的所有路径filelist都是相对于remoteuser主目录的。在这种情况下,如果没有--no-relative本地路径,则会像

/home/localuser/examplelocaldirectory/exampledirectory/examplefile123.tar.gz

如果远程命令是

cd exampledirectory && find . …

那么 中的所有路径filelist都将相对于remoteuser~/exampledirectory应该rsync使用remoteuser@remotemachine:exampledirectory。如果没有--no-relative本地路径,则

/home/localuser/examplelocaldirectory/examplefile123.tar.gz

看起来像是--no-relative使用过的文件。该选项对子目录仍然有影响。如果(远程)文件是,…/exampledirectory/foo/examplefile123.tar.gz那么您将获得

/home/localuser/examplelocaldirectory/examplefile123.tar.gz

或者

/home/localuser/examplelocaldirectory/foo/examplefile123.tar.gz

取决于您是否使用过--no-relative


提示和改进

  • --files-from=-rsync读取其标准输入。您需要一个命令,因此这将非常有用:

    ssh … 'find …' | rsync … --files-from=- …
    
  • 您说的是“所需文件”,一个文件;但一般来说,您可能会从中获得多个路径findrsync处理所有路径都没有问题。有几种方法可以限制您获得的内容:

    1. 更加严格find。例如find … -print -quit(如果-quit支持)仅获得一个结果(但可能不是您期望的结果)。
    2. 在远程端进行过滤。例如,ssh … 'find … | sort -R | head -n 1'只获取一个随机选择的结果。
    3. 在本地进行过滤。例如ssh … 'find …' | sort -R | head -n 1

    一般来说,在远程端进行过滤会减少您提取的数据量ssh。但如果远程机器速度慢/受限,并且过滤器会给 CPU 带来压力或需要大量内存,您可能需要提取更多数据并在本地端进行解析。

  • 在 Linux 中,文件名可以包含换行符。如果您遇到这种情况,则单个路径看起来就像列表中的多个条目。rsync将尝试检索不存在(或错误)的文件(或现有目录!)。如果find远程端支持-print0(可能支持也可能不支持),请将其用作最终操作,以及-0选项rsync。条目将以空字符结尾。命令将如下所示:

    ssh … 'find … -print0' > filelist
    rsync -0 …
    

    请注意,如果您想在传递给之前处理/过滤列表rsync,您使用的所有工具都必须将空字符视为分隔符。

你可以组合这些提示。例如:

ssh … 'find … -print0 | head -z -n 1' | rsync -0 … --files-from=- …

相关内容