Bagaimana cara terbaik menyalin banyak file kecil di atas scp?

59

Saya memiliki direktori yang memiliki beberapa gigabytes dan beberapa ribu file kecil. Saya ingin menyalinnya melalui jaringan dengan scp lebih dari sekali. Waktu CPU pada mesin sumber dan tujuan murah, tetapi overhead jaringan ditambah dengan menyalin setiap file secara individual sangat besar. Saya akan tar / gzip dan kirimkan, tetapi mesin sumber pendek pada disk.

Apakah ada cara bagi saya untuk menyalurkan output dari tar -czf <output> <directory>ke scp? Jika tidak, adakah solusi mudah lainnya? Mesin sumber saya kuno (SunOS) jadi saya lebih suka tidak menginstalnya.

nmichaels
sumber

Jawaban:

104

Anda dapat memasang tar di sesi ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"
pdo
sumber
3
Solusi +1 pipa tar. Jika Anda memiliki lebih banyak bandwidth dan lebih sedikit CPU Anda dapat menghapus flag kompresi (meskipun gzip cukup ringan).
dietbuddha
2
Dan Anda bisa menjatuhkan flag kompresi dan mengaktifkannya di SSH ( ssh -Catau Compression yesdi ~/.ssh/config).
sam hocevar
3
Tidak pernah terpikir untuk menggunakan tar seperti ini. Nah, itu sebabnya saya datang ke sini!
Tn. Shickadance
2
Perintah ini dapat dibuat sedikit lebih pendek:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito
2
@Greg tanda hubung adalah konvensi dalam perangkat lunak yang kompatibel dengan POSIX yang berarti STDIN atau STDOUT tergantung pada konteksnya. Tanda hubung pertama berarti 'baca dari / dev / stdin' dan yang kedua - yang sebenarnya dijalankan pada host jarak jauh - berarti '/ dev / stdin'. Pipa dan ssh menghubungkan kedua proses ini. Lihat unix.stackexchange.com/questions/16357/… untuk mempelajari lebih lanjut.
Richard Metzler
22

Tar dengan kompresi bzip2 harus mengambil banyak beban dari jaringan dan pada cpu.

$ tar -C /path/to/src/dir -jcf - ./ | ssh user@server 'tar -C /path/to/dest/dir -jxf -'

Tidak digunakan -vkarena output layar mungkin memperlambat proses. Tetapi jika Anda ingin output verbose menggunakannya di sisi lokal tar ( -jcvf), bukan pada bagian remote.

Jika Anda berulang kali menyalin di jalur tujuan yang sama, seperti memperbarui salinan cadangan, pilihan terbaik Anda adalah rsync dengan kompresi.

$ rsync -az -e ssh /path/to/src/dir/ user@server:/path/to/dest/dir/

Perhatikan bahwa kedua src dan jalur dest diakhiri dengan a /. Sekali lagi, tidak menggunakan -vdan -Pmenandai dengan sengaja, tambahkan mereka jika Anda membutuhkan output verbose.

forcefsck
sumber
16

gunakan rsync, itu menggunakan SSH.

Pemakaian:

rsync -aPz /source/path destination.server:remote/path

Switch rsync peduli dengan informasi kompresi dan I-Node. -Pmenampilkan progres setiap file.

Anda dapat menggunakan scp -C, yang memungkinkan kompresi, tetapi jika memungkinkan, gunakan rsync.

polemon
sumber
Sayangnya, rsync tidak tersedia di mesin sumber, dan tidak juga sshd.
nmichaels
1
sshd tidak diperlukan untuk operasi-operasi di mesin klien.
polemon
3

Anda dapat menjalankan tarkedua ujungnya menggunakan ssh. scpadalah bagian dari sshkeluarga kebaikan, jadi Anda mungkin memilikinya di kedua ujungnya.

 8:03AM 12 % tar cf - some_directory | ssh dest_host "tar xf -"

Mungkin ada cara untuk bekerja gzip atau bzip2 ke dalam pipa untuk mengurangi lalu lintas jaringan juga.

Bruce Ediger
sumber
3

@ pdo jawaban baik, tetapi orang dapat meningkatkan kecepatan dengan buffer dan kompresi yang baik dan menambahkan progress bar.

Seringkali jaringan menjadi penghambat dan kecepatan bervariasi dari waktu ke waktu. Oleh karena itu, ada baiknya Anda melakukan buffer data sebelum mengirimnya melalui jaringan. Ini bisa dilakukan dengan pv.

Selain itu, seseorang biasanya dapat meningkatkan kecepatan dengan algoritma kompresi yang tepat. Gzip (seperti yang digunakan di atas) adalah algoritma kompresi cepat, tetapi secara umum zstandard ( zstd) (dan untuk rasio kompresi tinggi LZMA / LZMA2 ( xz) akan memampatkan lebih baik dan lebih cepat pada waktu yang sama. Xz dan zstd baru memiliki dukungan multi-inti yang sudah ada Untuk menggunakan gzip dengan beberapa core pigz bisa digunakan.

Berikut adalah contoh untuk mengirim data dengan bilah kemajuan, buffering, dan kompresi zstandard melalui jaringan:

tar cf - . | pv -perabs $(du -sk . | cut -f 1)K | zstd -14 --long=31 -T0 | pv -qCB 512M | ssh user@host "cd /wherever && pv -qCB 512M | zstd -cd -T0 --long=31 | tar xf -"

Yang pertama pvadalah untuk menunjukkan kemajuan ( p ), perkiraan waktu ( e ), laju transfer ( r ), laju rata-rata ( a ), total byte yang ditransfer ( b ). Ukuran total diperkirakan dengan dudan ditambahkan ke pilihan ukuran ( s ). Kemajuan diukur sebelum kompresi dan buffering, karena itu tidak terlalu akurat, tetapi masih bermanfaat.

zstddigunakan dengan pengaturan kompresi 14 . Jumlah ini dapat dikurangi atau ditingkatkan tergantung pada jaringan dan kecepatan CPU sehingga zstd sedikit lebih cepat dari kecepatan jaringan. Dengan empat core pada Haswell, 3,2 GHz CPU 14 memberikan kecepatan sekitar 120 MB / s. Dalam contoh, mode panjang 31 (menggunakan jendela 2 GB, membutuhkan banyak RAM, tetapi sangat bagus misalnya untuk mengompres dump database) digunakan. The T0 pilihan menetapkan jumlah benang untuk jumlah core. Orang harus menyadari bahwa bersama dengan mode lama pengaturan ini menggunakan banyak memori.

Masalah dengan zstd adalah sebagian besar sistem operasi tidak memberikan versi> = 1.3.4. Versi ini diperlukan untuk dukungan multi-inti dan panjang yang tepat. Jika tidak tersedia, itu dapat dikompilasi dan diinstal dari https://github.com/facebook/zstd dengan adil make -j4 && sudo make install. Alih-alih zstd, kita juga bisa menggunakan xz atau pigz. xz lambat tetapi kompres sangat baik (bagus untuk koneksi lambat), pigz / gzip cepat tapi kompres tidak begitu baik. pvkemudian digunakan lagi, tetapi untuk buffering ( quntuk senyap, Cuntuk mode tanpa sambungan [selalu diperlukan untuk buffering] dan Buntuk mengatur ukuran buffer).

Dalam contoh buffer juga digunakan di sisi penerima. Ini seringkali tidak perlu (karena dekompresi dan kecepatan penulisan hard disk paling tinggi daripada kecepatan jaringan), tetapi biasanya juga tidak membahayakan.

Fabian Heller
sumber
2

Jika Anda memiliki gzip di kedua ujungnya: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Jika Anda tidak memiliki gzip di mesin sumber, pastikan Anda memiliki kompresi pada tujuan: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Ini akan lebih cepat daripada zip pertama kali, kemudian mengirim, kemudian membuka ritsleting, dan tidak memerlukan ruang disk tambahan di kedua sisi. Saya mengibarkan bendera kompresi (z) pada tar, karena Anda mungkin tidak memilikinya di sisi kuno.

MattBianco
sumber
2

Atau Anda bisa melakukannya sebaliknya jika perlu. Yaitu menarik tarball melalui jaringan daripada mendorongnya seperti yang disarankan. Ini tidak menyelesaikan bagian berulang dari pertanyaan Anda dan rsync adalah yang terbaik untuk itu tetapi mungkin ada switch tar untuk membantu.

Jadi pada mesin lokal:

ssh remote 'tar zcf - /etc/resolv.conf' | tar zxf -

Yang terbaik adalah berada di direktori yang benar terlebih dahulu atau Anda harus menggunakan -C beralih pada perintah yang tidak peduli di akhir.

Hanya menyebutkan ini kalau-kalau ini diperlukan. Bagi saya seperti dalam situasi saya server lokal saya ada di belakang nat, jadi akan mengambil beberapa jaringan untuk dapat melakukannya dengan cara yang sebelumnya telah disebutkan.

HTH

DaveQB
sumber
1

Atau pasang sistem file jarak jauh melalui sshfs

sshfs user@remotehost:/path/on/remote /path/on/local
ivanivan
sumber
1

Meskipun bukan yang paling elegan, terutama karena itu tidak menyalin satu file zip atau tar dan dua kali lipat sehingga tidak membantu mengurangi ovehead jaringan, satu-satunya pilihan saya adalah menggunakan scp -r:

-r

      Salin seluruh direktori secara rekursif. Perhatikan bahwa scp mengikuti tautan simbolis yang ditemui dalam traversal pohon.
Sumber: scp (1)

Saya mengalami masalah dengan kehabisan ruang disk dengan file tar zip 30 GB. Saya pikir gunzip dapat melakukannya secara inline, yaitu, menghapus yang asli karena sedang membuka ritsleting (dan saya mungkin melewatkan hasil Google) tetapi saya tidak dapat menemukan apa pun.

Akhirnya, karena saya bosan mencoba beberapa kali menunggu file TAR atau ZIP baru selesai tar'ing atau zip, akhirnya saya lakukan:

  1. Dari server / PC / laptop asli, navigasikan ke direktori tempat folder Anda dengan banyak file / folder berada.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Kemudian ambil bir, kopi atau popcorn dan tunggu. Untung saja, scp akan coba lagi jika koneksi jaringan "terhenti". Semoga saja tidak turun sepenuhnya.

JGlass
sumber
OK, ini jelas memakan waktu kurang dari mengetik seribu scpperintah. Tetapi pertanyaannya adalah tentang “overhead jaringan”. Apakah solusi Anda menggunakan jaringan kurang dari menyalin setiap file secara individual? Apakah solusi Anda lebih baik dari tujuh yang sudah diposting?
G-Man Mengatakan 'Reinstate Monica'
Snap, salah saya - saya benar-benar merindukan bagian overhead jaringan - terima kasih untuk menunjukkan bahwa @ G-Man. Saya memperbarui jawabannya, saya masih merasa mungkin berguna jika seseorang menemukan masalah yang sama seperti saya dan ketika saya menemukan pertanyaan ini.
JGlass