rsync, hapus file di sisi penerima yang dihapus di sisi pengiriman. (Tapi jangan hapus semuanya)

9

Saya ingin menggunakan rsync untuk ...

  • hapus file di sisi penerima yang juga dihapus di sisi pengirim
  • tidak menghapus file lain yang ada di direktori rsynced di sisi penerima

Sebagai contoh, katakanlah saya memiliki direktori local-src:

SEBELUM: local-src secara lokal mengandung ...

a.txt
b.txt
c.txt

direktori jarak jauh saya yang ingin saya sinkronkan ke konten local-srcdisebut remote-src.

SEBELUM: remote-src berisi ...

a.txt
b.txt
c.txt
d.txt
README.md

Katakanlah saya menghapus beberapa file di local-src:

SETELAH HAPUS LOKAL: local-src secara lokal mengandung ...

c.txt

Bagaimana saya bisa menggunakan rsync dengan cara memastikan bahwa file yang dihapus di sumber juga dihapus di tujuan, tetapi tanpa menghapus file lain di tujuan. Misalnya, saya ingin yang berikut ini di tempat tujuan:

SETELAH HAPUS LOKAL: remote-src berisi ...

c.txt
d.txt
README.md

Artinya, a.txtdan b.txtyang jauh dihapus juga, tetapi d.txtdan README.txtyang tersisa sendirian.

Apakah ada cara untuk mencapai ini dengan rsync?

EDIT: Putusannya sepertinya tidak mungkin dengan rsync. Saya ditanya mengapa saya membutuhkan ini, jadi untuk mengilustrasikan kasus penggunaan saya:

Katakanlah saya memiliki server web. Di server web itu, saya punya banyak direktori, misalkan saya punya direktori Adan apublic_html direktori tempat situs saya dilayani. Katakanlah saya memiliki beberapa proses otomatis yang menghasilkan file dalam direktori A. Saya ingin rsync (atau sync menggunakan beberapa alat lainnya) file yang dihasilkan atau diperbarui di Ake public_htmldirektori, tanpa menghapus file sewenang-wenang lainnya yang mungkin berada dalam public_html. Saya tentu saja tidak ingin rsync untuk secara tidak sengaja menghapus situs web saya.

Jika rsync bukan alat untuk pekerjaan ini, apakah orang lain tahu bagaimana saya bisa melakukan ini?

Heather Miller
sumber
2
Setelah membaca kembali pertanyaan Anda, saya rasa ini tidak mungkin dilakukan rsynckarena tidak ada cara untuk mengetahui file mana yang sudah ada di folder jauh. Anda mungkin perlu mencari alat lain.
Spack
rsync tidak akan membiarkan Anda melakukan ini, tetapi jika Anda scp seluruh direktori setiap kali Anda menghapus file Anda dapat menyimpannya dalam sinkronisasi, bukan solusi hanya saran.
Aadi Droid
1
Saya kira Anda sudah memikirkan hal ini, tetapi tidak bisakah Anda meletakkan file-file ini di subdirektori (atau di tempat lain) dan merujuknya dari public_html? Dengan begitu Anda memiliki satu direktori yang mudah dan secara eksplisit disinkronkan, tanpa mempengaruhi file di bagian lain dari sistem file server web.
MattJenko

Jawaban:

2

Apa yang ingin Anda lakukan adalah masuk akal, tetapi menggunakan rsyncuntuk melakukannya sendiri tidak. Jadi jawabannya tidak .

Alasannya sederhana: rsynctidak membuat riwayat apa yang ada di setiap direktori dan tidak memiliki cara untuk mengetahui apa yang perlu dihapus dan apa yang tidak. Bukan tanpa dukungan tambahan.

Anda harus bertanya pada diri sendiri mengapa Anda suka melakukan ini rsyncdan membuatnya lebih jelas. Ada program lain yang menggunakan librsync1.soyang lebih cerdas.


Dengan kendala santai yang tidak Anda perlukan rsyncsendiri, Anda dapat melihat rdiff-backup :

mkdir a
touch a/xx
touch a/yy
rdiff-backup a b
ls b 

Ini menunjukkan xxdan yysedang dalam b.

touch b/zz
rm a/xx
rdiff-backup a b

Ini menunjukkan xxdan zzsedang dalam b. rdiff-backupjuga menyimpan direktori rdiff-backup-datadi bsehingga Anda dapat rollback perubahan apapun, Anda harus membersihkan ini secara teratur menggunakanrdiff-backup perintah. (Contohnya adalah dengan file lokal untuk menunjukkan data tambahan di target tidak bisa dihapus, tetapi rdiff-backup berfungsi melalui jaringan juga).


Alternatif lain adalah menyiapkan beberapa sistem kontrol revisi terdistribusi (mercurial, bazaar, git). Dengan mercurial misalnya Anda dapat memiliki skrip (saya menggunakan Makefile untuk itu), yang mendorong semua perubahan ke server dan kemudian melakukan pembaruan dari file yang diperiksa di sana, abaikan file tambahan yang ada di server jauh (tetapi memiliki tidak dimasukkan di bawah kendali revisi).

Di server Anda akan melakukan:

hg init
hg add file_list_excluding_that_should_not_should_be_deleted_if_not_on_client
hg commit -m "initial setup"

Pada klien:

hg clone ssh://username@server/dir_to_repository

Sekarang jika Anda menghapus file pada klien dan lakukan:

hg commit -m "removed file"
ssh username@server "cd dir_to_repository; hg update --clean"

File Anda dihapus dihapus di server, tetapi data lain (tidak ditambahkan ke repositori) tidak bisa dihapus.

Anthon
sumber
Saya dapat menerima bahwa rsync tidak akan melakukan ini. Tapi saya tidak setuju bahwa ini tidak mungkin dengan rsync- jika rsync tahu di sisi pengirim file mana yang telah dihapus, mengapa tidak dapat mengirim informasi itu ke sisi penerima di diff? Setelah membandingkan untuk kesegaran, saya tidak melihat mengapa sisi penerima tidak bisa hanya menghapus file yang diindikasikan untuk dihapus di diff, tanpa menghapus semua yang lain dalam direktori. Menghapus setiap file tidak bersalah lainnya (tidak terhapus pada sumbernya) dalam direktori tampaknya tidak masuk akal bagi saya.
Heather Miller
Bagaimanapun, alasan saya membutuhkan ini adalah sebagai berikut. Saya memiliki direktori, sebut saja A, di mana beberapa proses otomatis, dan file secara otomatis dihasilkan di sana. Saya punya server web, dan saya ingin file-file di dalamnya Auntuk disinkronkan kembali ke public_htmldirektori server web, tentu saja tanpa menghapus semua yang lain di public_htmlfolder server web. Jika ada yang punya ide untuk mencapai ini dengan alat lain, itu akan lebih dari diterima. Saya akan memperbarui pertanyaan saya untuk mencerminkan hal ini.
Heather Miller
Untuk memperjelas komentar pertama saya di atas - saya seharusnya mengatakan "Saya tidak setuju bahwa sesuatu seperti ini tidak mungkin dilakukan dengan alat seperti rsync". Secara intuitif, sepertinya ini tidak mungkin terlalu sulit untuk dicapai (kecuali saya kehilangan sesuatu).
Heather Miller
Hmm baiklah. Saya rasa saya melihat sekarang - bagaimana rsync bisa tahu kapan sesuatu dihapus di local-srcdirektori tanpa ada proses mengawasi direktori itu untuk perubahan. Mungkin ini akan sulit.
Heather Miller
@HeatherMiller Seperti yang saya tulis, permintaan Anda masuk akal, tetapi rsyncbukan alat. Harap sadari bahwa syncin rsyncberasal dari sinkronisasi dan bukan itu yang ingin Anda lakukan. Dalam pengembangan rsyncfokus telah efisien (meminimalkan) transfer data. Alat-alat lain seperti rdiff-backup(dan mungkin cvsup) telah menggunakan tekniknya untuk itu tetapi membangunnya dengan fitur tambahan.
Anthon
1

Saya tidak berpikir ini mungkin tanpa secara eksplisit mengecualikan file di sisi penerima sebagai bagian dari perintah rsync. Lihat bagian halaman manual untuk rsync: "ATURAN DAN HAPUS PER-DIREKTORI".

Tanpa opsi hapus, aturan per direktori hanya relevan di sisi pengiriman, sehingga Anda dapat dengan bebas mengecualikan file gabungan itu sendiri tanpa mempengaruhi transfer. Untuk mempermudah ini, pengubah 'e' menambahkan pengecualian ini untuk Anda, seperti terlihat dalam dua perintah setara ini:

          rsync -av --filter=': .excl' --exclude=.excl host:src/dir /dest
          rsync -av --filter=':e .excl' host:src/dir /dest

Namun, jika Anda ingin menghapus di sisi penerima DAN Anda ingin beberapa file dikecualikan dari dihapus, Anda harus memastikan bahwa pihak penerima tahu file apa yang harus dikecualikan. Cara termudah adalah dengan memasukkan file gabungan per-direktori dalam transfer dan gunakan --delete-after, karena ini memastikan bahwa sisi penerima mendapatkan semua aturan pengecualian yang sama dengan sisi pengiriman sebelum mencoba menghapus apa pun:

          rsync -avF --delete-after host:src/dir /dest

Namun, jika file gabungan bukan bagian dari transfer, Anda harus menentukan beberapa aturan pengecualian global (yaitu ditentukan pada baris perintah), atau Anda harus memelihara file gabungan per-direktori Anda sendiri pada sisi penerima. Contoh yang pertama adalah ini (anggap file remote .rules mengecualikan diri mereka):

   rsync -av --filter=’: .rules’ --filter=’. /my/extra.rules’
      --delete host:src/dir /dest

Dalam contoh di atas file extra.rules dapat memengaruhi kedua sisi transfer, tetapi (di sisi pengirim) aturannya tunduk pada aturan yang digabung dari file .rules karena mereka ditentukan setelah aturan gabungan per-direktori.

Dalam satu contoh terakhir, sisi jarak jauh mengecualikan file .rsync-filter dari transfer, tetapi kami ingin menggunakan file .rsync-filter kami sendiri untuk mengontrol apa yang akan dihapus pada sisi penerima. Untuk melakukan ini kita harus secara khusus mengecualikan file gabungan per-direktori (sehingga mereka tidak terhapus) dan kemudian memasukkan aturan ke dalam file lokal untuk mengontrol apa lagi yang tidak boleh dihapus. Seperti salah satu dari perintah ini:

       rsync -av --filter=':e /.rsync-filter' --delete \
           host:src/dir /dest
       rsync -avFF --delete host:src/dir /dest
slm
sumber
0

Jika saya mengerti dengan benar, --excludemungkin itu yang Anda cari:

$ ls src dst
dst:
a.txt  b.txt  c.txt  d.txt  README.md

src:
c.txt
$ rsync --update --delete --recursive --exclude="d.txt" --exclude="README.md" src/ dst
$ ls src dst
dst:
c.txt  d.txt  README.md

src:
c.txt
Spack
sumber
Ya tidak. Saya tidak ingin harus mendaftar secara manual semua file yang ingin saya kecualikan. Saya hanya ingin rsync hanya untuk menghapus file yang telah saya hapus pada sumbernya - saya tidak perlu tahu di sumbernya apa file lain yang mungkin ada di direktori yang sama di tujuan.
Heather Miller
0

Saya punya jawaban untuk itu. Saya pikir itu berhasil. Dan itu berhasil untuk saya. Pertama, Anda harus mem- rsyncremote file ke file lokal. Kemudian sisi lokal berisi semua file.

sudo rsync -r -a -v --delete /[email protected]:/remote_dir/ /local_dir/

sekarang di sisi lokal

a.txt
b.txt
c.txt
d.txt
README.md

Kemudian Anda dapat menghapus file atau melakukan apa pun yang Anda inginkan. (Di sisi lokal). Di pertanyaan Anda, Anda menghapus file-file ini.

file yang dihapus

a.txt
b.txt

Setelah itu Anda dapat rsyncfile lokal ke sisi jarak jauh. Kemudian kedua belah pihak memiliki file yang sama.

sudo rsync -r -a -v --delete /local_dir/ [email protected]:/remote_dir/

memberikan

c.txt
d.txt
README.md

file di sisi remote dan sisi lokal. (Dengan menggunakan --delete, itu menghapus file lain di sisi remote yang tidak cocok dengan sisi lokal ).

Demikianlah Sumanadasa
sumber