基本上就是标题。
以下是我迄今为止取得的成功:
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/
、-type
和f
。最后一个是-name
examplefile*
没有引号,因为引号被本地 shell “使用”。实际上,由远程ssh
shell 构建并运行的远程命令是
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=- …
您说的是“所需文件”,一个文件;但一般来说,您可能会从中获得多个路径
find
。rsync
处理所有路径都没有问题。有几种方法可以限制您获得的内容:- 更加严格
find
。例如find … -print -quit
(如果-quit
支持)仅获得一个结果(但可能不是您期望的结果)。 - 在远程端进行过滤。例如,
ssh … 'find … | sort -R | head -n 1'
只获取一个随机选择的结果。 - 在本地进行过滤。例如
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=- …