リモートでスキーマの最新の2つのファイルを同期します。

リモートでスキーマの最新の2つのファイルを同期します。

異なる環境にある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一緒に試してみましたが、完了していない段階で失敗しました。rsyncssh

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/

rsyncwithオプションを試しましたが、--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欲しいです。sshtest_anonym_21-11-2023.logtest_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

ターゲットユーザーのログインシェルがremoteHostzshの場合は、次のようにします。

rsync --old-args 'remoteHost:folder/test_anonym*.(log|gz)(.om[1,2])' ~/folder/

この動作はデフォルトではなく、最新バージョンでは必須であり、呼び出すリモート--old-argsシェルコマンドラインからそのまま渡され、シェルは名前から最後の2つのファイルに一致するglobを次に開始または拡張します。またはで終わります。rsyncfolder/test_anonym*.(log|gz)(.om[1,2])rsync --serverfoldertest_anonym.gz.log

次のコマンドを実行すると、--old-args使用されているかどうかによる動作の違いを見つけることができます。--protect-argsrsyncstrace -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_STRINGbashは自動的に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つのコマンドにパイプするか、およびを保存することですlssortgrepheadtmpしかし、--include-from=これを支持してくれる人は誰もいないようです。

関連情報