異なる環境にある2つのサーバー間で、特定のスキーマの最新の2つのファイルを同期したいと思います。
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
コマンドは、1つのファイル形式に対してのみモードを使用し、2つの形式の最新のファイルを認識しないため、送信しすぎます。
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/
必要なファイルを見つけて同期するためにすべてを1つにまとめる方法(または可能であれば)がわかりません。今は本当に詰まっています。どうすればいいですか?私はそれを私のワークステーションで使用しzsh
、私のリモコンでも使用しますbash
。
ここで私の期待をもう一度言うと、私はリモートで私のパターンと一致し、そのタイプの最新の2つのファイル、iEとWitchの異なるタイプの2つのファイルがrsync
欲しいです。ssh
test_anonym_21-11-2023.log
test_anonym_21-11-2023.dmp.gz
答え1
GNUツールがある場合は、それを使用してfind
最新の2つの変更されたファイルを識別し、それらのファイルのみを転送できます。リモートホストからファイルを抽出する必要があるため、プロセスは少し複雑ですが、これはssh
より多くの参加が必要であることを意味します。
最後に変更された2つのファイルが転送されるファイルのペアであると仮定でき、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
ターゲットユーザーのログインシェルがremoteHost
zshの場合は、次のようにします。
rsync --old-args 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/
この動作はデフォルトではなく、最新バージョンでは必須であり、呼び出すリモート--old-args
シェルコマンドラインからそのまま渡され、シェルは名前から最後の2つのファイルに一致する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
[...]
\
リモートシェルに有効かどうかにかかわらず、一部の文字はエスケープされます。
$ 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はシェルコマンドラインからは渡されませんが、最新のrsyncプロトコルでは帯域内に渡されます。通常、これは最も安全ですが、シェルの高度なワイルドカードは使用できません。
zshがリモートホストにインストールされているがユーザーのログインシェルがbashの場合は、次のトリックを使用してzhがrsyncサーバーコマンドを実行するようにbashを説得できます。
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
私の元の質問:
「異なる環境にある2つのサーバー間で、特定のスキーマの最新の2つのファイルを同期したいと思います。」
私の(送信)ホストサーバーには最新のファイルが含まれています。
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)別のサーバーで命名パターンとファイルタイプを使用して2つの最新のファイルを識別し、出力を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
を1つのコマンドにパイプするか、およびを保存することですls
。sort
grep
head
tmpしかし、--include-from=
これを支持してくれる人は誰もいないようです。