我想在不同环境中的两台服务器之间同步特定模式的最新两个文件:
drwxrwxr-x 2 transfer transfer 4096 28. Nov 13:05 .
drwxr-xr-x 7 transfer transfer 4096 28. Nov 13:05 ..
-rw-rw-r-- 1 transfer transfer 11151643678 28. Nov 12:46 test_28-11-2023.dmp.gz
-rw-rw-r-- 1 transfer transfer 29789 28. Nov 13:04 test_28-11-2023.log
-rw-r--r-- 1 transfer transfer 10770251760 28. Nov 13:00 test_anonym_19-11-2023.dmp.gz
-rw-r--r-- 1 transfer transfer 48408 28. Nov 13:02 test_anonym_19-11-2023.log
-rw-r--r-- 1 transfer transfer 9329096219 28. Nov 13:03 test_anonym_21-11-2023.dmp.gz
-rw-r--r-- 1 transfer transfer 48407 28. Nov 13:03 test_anonym_21-11-2023.log
由于只想传输最新的模式,*.gz
我可以执行以下操作来识别它们:*.log
\.\/test_anonym_.*\.*
user@host:~/folder$ find . -type f -regex '\.\/test_anonym_.*\.*' | sort -r | head -n 2
./test_anonym_21-11-2023.log
./test_anonym_21-11-2023.dmp.gz
或者直接在遥控器上识别它们,ssh
如下所示(效果很好):
user@host:~/folder$ ssh -qx user@host "ls -t /home/user/folder | sort -r | head -n 2"
test_anonym_21-11-2023.log
test_anonym_21-11-2023.dmp.gz
以下rsync
命令传输太多,因为我只使用一种文件类型的模式,而没有识别两种类型的最新文件:
user@host:~/folder$ rsync -av --stats --include='test_anonym_*.gz' --exclude='test_*.*' user@host:/home/user/folder/ /home/user/folder/
test_anonym_19-11-2023.dmp.gz
test_anonym_21-11-2023.dmp.gz
在筛选了许多手册页和类似的帖子后,我尝试将ssh
和一起使用,但它在从未完成的步骤中失败了:rsync
ssh
ssh user@host "ls -t /home/user/folder/ | sort -r | head -n 2" | rsync -0 --stats --files-from=- -av user@host:/home/user/folder/ /home/user/folder/
我尝试使用rsync
with--files-from=
选项,但也失败了,因为我不确定两个示例中的语法:
rsync -a --stats --files-from=<(ssh user@host 'find . -type f -regex '\./test_anonym_.*\.*' | sort -r | head -n 2') --exclude='test_*.*' user@host:/home/user/folder/ /home/folder/folder/
rsync -a --stats --files-from=<(find . -type f -regex '\.\/test_anonym_.*\.*' | sort -r | head -n 2) --exclude='test_*.*' user@host:/home/user/folder/ /home/folder/folder/
我不确定如何将它们放在一起(或者是否可能)来查找和同步所需的文件;我现在真的被困住了。我怎样才能做到这一点?我的工作站使用zsh
,我的遥控器都使用bash
。
在这里重申我的期望:我想rsync
(有/没有ssh
)来自远程的两个不同类型的文件,iEtest_anonym_21-11-2023.log
和test_anonym_21-11-2023.dmp.gz
女巫与我的模式匹配,并且是其类型的最新两个文件。
答案1
如果您有 GNU 工具,您可以使用它find
来识别两个最近修改的文件并仅传输这些文件。由于需要从远程主机提取文件,该过程有点复杂,但这意味着ssh
需要更多的参与。
如果我们可以假设最近修改的两个文件是一对要传输的文件,并且我们有带有 GNU 扩展名(或类似扩展名)的工具:
ssh -qn remoteHost "find folder -name 'test_anonym_*' -printf '%T@ %p\0'" |
sort -z -k1,1rn |
head -z -n2 |
cut -z -d' ' -f2- |
rsync --dry-run -av --files-from - --from0 remoteHost: "$HOME/folder"
如果您没有 GNU 工具,则必须小心意外的文件名,但只要您可以控制放置在以下位置的文件名,此管道就可以工作folder
:
ssh -qn remoteHost ls -t folder |
head -n2 |
rsync --dry-run -av --files-from - --from0 remoteHost:folder/ "$HOME/folder"
在这两种情况下,--dry-run
当您对代码执行您期望的操作感到满意时,请将其删除。
如果您只能保证(比如说)文件dmp.gz
并且您想要提取关联的log
文件,那么情况会变得更加复杂。但你的问题似乎并不需要这样做。
答案2
如果目标用户的登录 shellremoteHost
是 zsh,则只需执行以下操作:
rsync --old-args 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/
对于,在该行为不再是默认行为--old-args
的较新版本中需要,会在调用 的远程 shell 命令行中按原样传递,并且 shell 将扩展该 glob,该 glob 与名称中的两个最新文件相匹配以 或 开头并以或结束。rsync
folder/test_anonym*.(log|gz)(.om[1,2])
rsync --server
folder
test_anonym
.gz
.log
您可以通过运行以下命令来发现使用--old-args
和不使用以及使用时行为的差异:--protect-args
rsync
strace -e execve
$ strace -fe execve rsync --old-args 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/
[...]
[pid 8483] execve("/bin/ssh", ["ssh", "remoteHost", "rsync", "--server", "--sender", "-e.LsfxCIvu", ".", "folder/test_anonym*.(log|gz)(.om"...], 0x7ffceb4e2cf0 /* 52 vars */) = 0
[...]
Arg 未修改就通过了。
$ strace -fe execve rsync 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/
[...]
[pid 8489] execve("/bin/ssh", ["ssh", "remoteHost", "rsync", "--server", "--sender", "-e.LsfxCIvu", ".", "folder/test_anonym*.\\(log\\|gz\\)\\"...], 0x7ffc5bced518 /* 52 vars */) = 0
[...]
某些字符使用 转义\
,无论这对远程 shell 是否有效。
$ strace -fe execve rsync --protect-args 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/
[...]
[pid 8507] execve("/bin/ssh", ["ssh", "remoteHost", "rsync", "--server", "--sender", "-se.LsfxCIvu"], 0x7ffc404a9900 /* 52 vars */) = 0
[...]
arg 不是在 shell 命令行中传递的,而是在较新的 rsync 协议中带内传递的。一般来说,这是最安全的,但这不允许我们使用 shell 的高级通配符。
如果 zsh 安装在远程主机上,但用户的登录 shell 是 bash,您可以使用如下技巧说服 bash 让 zsh 运行 rsync 服务器命令:
rsync --rsync-path='zsh -c "${BASH_EXECUTION_STRING#*\#\ }" # rsync' \
--old-args 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/
远程主机上的 bash 将被要求评估:
zsh -c "${BASH_EXECUTION_STRING#*\#\ }" # rsync --server --sender -e.LsfxCIvu . folder/test_anonym*.(log|gz)(.om[1,2])
整个rsync --server...
命令仅被视为注释。
$BASH_EXECUTION_STRING
bash 自动将 bash 设置为正在执行的内联脚本,并且我们从其中删除直到第一次出现 的所有内容#
,因此zsh
将进行解释:
rsync --server --sender -e.LsfxCIvu . folder/test_anonym*.(log|gz)(.om[1,2])
如果您不需要同步的能力,rsync
但只需要传输这些文件,这样做可能更容易:
ssh remoteHost zsh << 'EOF' | (cd ~/folder && tar zxpvf -)
cd folder &&
tar zcf - test_anonym*.(log|gz)(.om[1,2])
EOF
答案3
我原来的问题:
“我想在不同环境中的两台服务器之间同步特定模式的最新两个文件。”
我的(传输)主机服务器包含最新文件:
drwxrwxr-x 2 transfer 4,0K 26. Mär 13:30 .
drwxr-xr-x 6 transfer 4,0K 20. Mär 11:01 ..
-rw-rw-r-- 1 transfer 0 26. Mär 13:30 test_26-03-2024.dmp.gz
-rw-rw-r-- 1 transfer 0 26. Mär 13:30 test_26-03-2024.log
-rw-rw-r-- 1 transfer 0 28. Nov 12:46 test_28-11-2023.dmp.gz
-rw-rw-r-- 1 transfer 21 28. Nov 13:04 test_28-11-2023.log
-rw-rw-r-- 1 transfer 0 26. Mär 13:30 test_anonym_17-03-2024.dmp.gz
-rw-rw-r-- 1 transfer 0 26. Mär 13:30 test_anonym_17-03-2024.log
-rw-r--r-- 1 transfer 0 28. Nov 13:00 test_anonym_19-11-2023.dmp.gz
-rw-r--r-- 1 transfer 5 29. Jan 13:35 test_anonym_19-11-2023.log
-rw-r--r-- 1 transfer 0 28. Nov 13:03 test_anonym_21-11-2023.dmp.gz
-rw-r--r-- 1 transfer 497 29. Jan 13:36 test_anonym_21-11-2023.log
-rw-rw-r-- 1 transfer 0 29. Jan 13:38 test_anonym_29-01-2024.dmp.gz
-rw-rw-r-- 1 transfer 201 29. Jan 13:37 test_anonym_29-01-2024.log
user@transfer:~/folder$
我的问题的解决方案:
我从我的(devops)其他服务器中识别了命名模式和文件类型的两个最新文件,test_anonym_*.*
并将输出保存为文本文件:.log
.dmp.gz
user@devops:~$ ssh -qx user@transfer 'ls -tr /home/user/folder | sort -k 8,8n -k 6,6M | grep test_anonym_* | head -n 2' > output.txt
...
user@devops:~$ nl output.txt
1 test_anonym_17-03-2024.dmp.gz
2 test_anonym_17-03-2024.log
我现在可以将rsync
文本文件中包含的文件发送到其他服务器:
user@devops:~$ rsync -arv --stats --include-from=output.txt --exclude=* user@transfer:folder/ ./folder/
user@transfer's password:
receiving incremental file list
./
test_anonym_17-03-2024.dmp.gz
test_anonym_17-03-2024.log
...
sent 139 bytes received 211 bytes 100,00 bytes/sec
total size is 0 speedup is 0,00
正确的文件已传输,我的主要问题已解决:
user@devops:~$ ls -la folder/
drwxrwxr-x 2 user user 4096 26. Mär 13:30 .
drwxr-xr-x 4 user user 4096 26. Mär 14:55 ..
-rw-rw-r-- 1 user user 0 26. Mär 13:30 test_anonym_17-03-2024.dmp.gz
-rw-rw-r-- 1 user user 0 26. Mär 13:30 test_anonym_17-03-2024.log
很高兴有:
现在的解决方案是通过管道将ssh
和rsync
命令合并为一个命令,或者将ls
, sort
,grep
和保存head
到tmp但--include-from=
似乎没有人能够为此提供支持。