Bản sao đệ quy sh (cp -r) - Cách loại trừ thư mục con


8

Tôi cần chạy một tập lệnh từ xa bằng cách sử dụng sshthông qua Ruby( net / ssh ) để sao chép đệ quy một thư mục và loại trừ thư mục con. Tôi đang tìm cách nhanh nhất để làm điều đó rsynclà không tốt. Ngoài ra, tôi hiểu rằng sshsử dụng shvà không bash.

Trong bash tôi làm:

cp -r srcdir/!(subdir) dstdir

và nó hoạt động tốt. Tuy nhiên khi tôi khởi chạy tập lệnh thông qua sshtôi nhận được lỗi

sh: 1: Syntax error: "(" unexpected

bởi vì nó được sử dụng sh.

Tôi đã kiểm tra shtrang man, nhưng không có tùy chọn để loại trừ các tập tin.

Đó có phải là giả định của tôi về sshviệc sử dụng shđúng? Bất kỳ đề nghị thay thế?

EDIT 1: Trong trường hợp nó hữu ích, đầu ra của sudo cat /etc/shells:

# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/tmux
/usr/bin/screen

EDIT 2: OK. Vì vậy, bash nó có sẵn và đó dường như không phải là vấn đề. Tôi đã xác minh rằng ssh thực sự đang sử dụng bash. Vấn đề dường như có liên quan đến việc thoát dấu ngoặc đơn hoặc dấu chấm than. Tôi đã thử chạy lệnh từ shell (macos) và đây là lệnh thực tế:

ssh -i .ssh/key.pem ubuntu@X.X.X.X 'mkdir /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/N; cp -r /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/mesh/!\(constant\) /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/N; ln -s /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/mesh/constant /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/N/constant'

Theo cách này tôi nhận được một lỗi khác

cp: cannot stat '/home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/mesh/!(constant)': No such file or directory

EDIT 3: Dựa trên các ý kiến ​​tôi đã thay đổi lệnh thêmextglob

Nếu tôi sử dụng

ssh -i .ssh/key.pem ubuntu@X.X.X.X 'shopt -s extglob; mkdir /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/N; cp -r /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/mesh/!\(constant\) /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/N; ln -s /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/mesh/constant /home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/N/constant'

Tôi nhận được lỗi sau:

cp: cannot stat '/home/ubuntu/OpenFOAM/ubuntu-4.1/run/LES_New-Area_residuals2/mesh/!(constant)': No such file or directory

Nếu tôi không thoát khỏi dấu ngoặc đơn tôi nhận được

bash: -c: line 0: syntax error near unexpected token `('

3
ssh(cũng sshd) sử dụng shell đăng nhập của người dùng từ xa. Có thể là bất cứ thứ gì.
Stéphane Chazelas

Unix không có thư mục, chỉ có thư mục. :)
tchrist

1
Trong những tình huống như thế này, tôi thường chỉ muốn phát triển tập lệnh trên máy chủ từ xa, sau đó 1) để nó ở đó, ssh in (lập trình nếu cần) và thực hiện nó hoặc 2) nếu nó thay đổi mỗi lần, quét nó qua, thực thi nó thông qua ssh, và sau đó xóa nó. Một bước bổ sung có thể, nhưng bạn không kết thúc với việc thoát khỏi những cơn ác mộng và những cơn ảm đạm mở rộng cục bộ thay vì từ xa và tất cả những thứ đó. Nếu không, tôi sẽ luôn sử dụng định dạng heredoc như @ StéphaneChazelas sử dụng bên dưới.
Josh Rumbut

Câu trả lời:


10

SSH chạy shell đăng nhập của bạn trên hệ thống từ xa, bất kể đó là gì. Nhưng !(foo)yêu cầu shopt -s extglob, mà bạn có thể không đặt trên điều khiển từ xa.

Hãy thử điều này để xem SSH có chạy Bash ở phía xa không:

ssh me@somehost 'echo "$BASH_VERSION"'

Nếu điều đó in bất cứ điều gì, nhưng các tập lệnh khởi động của bạn không được đặt extglob, bạn có thể thực hiện bằng tay với lệnh được truyền tới ssh:

ssh me@somehost 'shopt -s extglob
    echo srcdir/!(subdir)'                                 
 # or
ssh me@somehost $'shopt -s extglob\n echo srcdir/!(subdir)'   

extglob ảnh hưởng đến việc phân tích cú pháp của dòng lệnh và chỉ có hiệu lực sau một dòng mới, vì vậy chúng ta phải đặt một dòng mới theo nghĩa đen ở đó, một dấu chấm phẩy là không đủ.

ssh tôi @ somehost 'shopt -s extglob; echo srcdir /! (subir) '

Cũng không phải là nếu bạn thoát dấu ngoặc đơn bằng dấu gạch chéo ngược, chúng sẽ mất các thuộc tính đặc biệt của chúng, giống như bất kỳ ký tự toàn cầu nào khác. Đây không phải là những gì bạn muốn làm trong trường hợp này.

$ touch foo bar; shopt -s extglob; set +o histexpand
$ echo *
bar foo
$ echo !(foo)
bar
$ echo \*
*
$ echo !\(foo\)
!(foo)

10

Tôi không biết tại sao bạn nghĩ rằng rsync sẽ chậm. Tốc độ của một bản sao chủ yếu được xác định bởi tốc độ của đĩa. Rsync có nhiều tùy chọn để chỉ định những gì bạn muốn bao gồm và loại trừ, do đó, nó cung cấp cho bạn quyền kiểm soát tốt hơn nhiều so với shell shellbing.

Là trạng thái thủ công bash, !(patter)chỉ được nhận dạng trong bash nếu extglobđược đặt. Trong ví dụ của bạn, bạn đã không đặt extglob. Hơn nữa, một bashkhởi đầu như shvẫn còn bash, nhưng sẽ vô hiệu hóa một số tiện ích mở rộng để tương thích.

Máy chủ SSH sẽ khởi động trình đăng nhập của người dùng, như được chỉ định trong /etc/passwd. Bạn có thể thay đổi vỏ hoặc sử dụng vỏ đó để bắt đầu một vỏ khác phù hợp với nhu cầu của bạn hơn.


Tôi đã thử nghiệm với time. time cp -r mesh/!(constant) N-> 1.04 thực và time rsync -a mesh/ N --exclude=constant-> 1.8 thực
Rojj

7
@Rojj đó là táo để so sánh cam. Đối với một điều, bạn đang sử dụng -a cho rsync nhưng không phải cho cp. Điều đó liên quan đến việc bảo vệ các quyền và các thuộc tính khác, vì vậy bạn không thực sự làm điều tương tự.
tự đại diện

6

Một vài lưu ý đầu tiên:

  • máy chủ ssh không bắt đầu shdiễn giải dòng lệnh được gửi bởi máy khách, nó chạy shell đăng nhập của người dùng trên máy chủ từ xa, như that-shell -c <the-string-provided-by-the-client>. Shell đăng nhập của người dùng từ xa có thể là bất cứ điều gì. Hãy nhớ rằng một số shell thích tcsh, fishhoặc rccó cú pháp rất khác so với sh.
  • nó thực sự là một dòng lệnh, hay chính xác hơn là một chuỗi (có thể chứa các ký tự dòng mới, vì vậy một số dòng). Thậm chí nếu bạn làm ssh host cmd arg1 'arg 2'ở đâu cmd, arg1arg 2ba đối số truyền cho ssh, sshmóc nối những lập luận với không gian và thực sự sẽ gửi cmd arg1 arg 2chuỗi sshd, và remote shell sẽ chia thành rằng cmd, arg1, arg2.
  • !(subdir)là một nhà điều hành toàn cầu (một kshnhà điều hành toàn cầu cũng được hỗ trợ bởi zsh -o kshglobbash -O extglob). Giống như tất cả các quả cầu, nó loại trừ các tệp ẩn, vì vậy hãy cẩn thận có thể có các tệp khác mà nó loại trừ.

Ở đây, để tránh vấn đề tìm ra cú pháp đúng cho shell từ xa, bạn thực sự có thể nói với shell khác để khởi động shell mà bạn muốn và cung cấp mã cho nó thông qua stdin (một trong các tùy chọn được liệt kê tại Cách thực hiện đơn giản tùy ý lệnh trên ssh mà không biết shell đăng nhập của người dùng từ xa? )

ssh host 'bash -O extglob -O dotglob' << 'EOF'
cp -r srcdir/!(subdir) dstdir/
EOF

bash -O extglob -O dotgloblà một dòng lệnh được hiểu giống nhau bởi tất cả các shell chính, bao gồm cả những cái giống như Bourne, csh, rc, fish ... Phần trên sẽ hoạt động miễn là bashđược cài đặt và nằm trong người dùng $PATH(mặc định $PATH, có thể được sửa đổi bởi người dùng đăng nhập shell như với ~/.zshenvcho zsh, ~/.cshrccho csh, ~/.bashrccho bash).

POSIXly (mặc dù trong thực tế, bạn có thể thấy rằng nhiều hệ thống có bashlệnh hơn paxlệnh), bạn có thể làm:

ssh host sh << 'EOF'
cd srcdir && pax -rw -'s|^\.//\./subdir\(/.*\)\{0,1\}$||' .//. /path/to/destdir/
EOF

-sáp dụng thay thế cho các đường dẫn được chuyển. Khi sự thay thế đó mở rộng thành không có gì, tập tin sẽ bị loại trừ. Vấn đề là sự thay thế cũng được áp dụng cho mục tiêu của các liên kết tượng trưng. Đó là lý do tại sao chúng tôi sử dụng .//.ở trên để làm cho ít có khả năng một liên kết tượng trưng bị ảnh hưởng.


4

Tôi không nghĩ sshlà giới hạn trong việc sử dụng sh. Nó phụ thuộc vào những gì được cài đặt trên hệ thống đích, cách người dùng được thiết lập và những gì được phép sử dụng /etc/shells.

Bạn đã xem xét chshlệnh?


4

Nếu bạn muốn làm điều đó một cách nhanh chóng, bạn có thể xem xét rsyncvới một thuật toán mã hóa khác. Điều này cung cấp cho bạn tùy chọn để dễ dàng loại trừ vv, với tốc độ hy sinh không nhiều.

rsync -aHAXxv --numeric-ids --progress -e "ssh -T -c arcfour -o Compression=no -x" user@<source>:<source_dir> <dest_dir>

cùng với việc thêm arcfourmã hóa để vạch xuất phát với Cipherstrong /etc/ssh/ssh_config, nếu chưa được kích hoạt, mang đến cho bạn một tốc độ chấp nhận được.

CẢNH BÁO: arcfourMã hóa không an toàn . KHÔNG chạy cái này trên các kênh không an toàn. Nếu bạn lo ngại về việc truy cập vào máy chủ từ các kênh không an toàn bằng cách sử dụng arcfourmã hóa, hãy thay đổi phần etc/ssh/ssh_configvới máy chủ dành riêng cho máy chủ nguồn của bạn - Tạo một Hostphần trong ssh_config cho máy chủ nguồn của bạn, bạn có thể sử dụng Ciphers arcfourở đó để phản chiếu công -ctắc trên , hạn chế arcfourmã hóa cho máy chủ này.

Để biết chi tiết, tham khảo ssh_configtrang người đàn ông.

Tuy nhiên, nếu CPU của bạn hỗ trợ tập lệnh AES-NI, hãy thử chuyển sang aes128-gcm@openssh.com (vâng, đó là tên mật mã, bao gồm cả @ Stuff), sẽ sử dụng AES128 nhanh chóng (với AES-NI) -GCM.

Vì vậy, với CPU hỗ trợ AES-NI, hãy thay đổi "ssh -T -c arcfour -o Compression=no -x"để "ssh -T -c aes128-gcm@openssh.com -o Compression=no -x"có kết quả an toàn hơn.

Giải trình

rsync

  • (Đừng sử dụng -z, nó chậm hơn nhiều)
  • a: chế độ lưu trữ - giải cứu, giữ nguyên chủ sở hữu, giữ quyền, bảo toàn thời gian sửa đổi, bảo tồn nhóm, sao chép liên kết tượng trưng dưới dạng liên kết tượng trưng, ​​bảo toàn tệp thiết bị.
  • H: bảo tồn các liên kết cứng
  • A: bảo quản ACL
  • X: bảo tồn các thuộc tính mở rộng
  • x: không vượt qua ranh giới hệ thống tệp
  • v: tăng tính dài dòng
  • --numeric-ds: không ánh xạ các giá trị uid / gid theo tên người dùng / nhóm
  • nếu bạn cần đồng bộ hóa, hãy thêm --delete: xóa các tệp không liên quan khỏi các dir dir (dọn dẹp vi sai trong quá trình đồng bộ hóa)
  • --progress: hiển thị tiến trình trong quá trình chuyển

ssh

  • T: tắt pseudo-tty để giảm tải cpu về đích.
  • c arcfour: sử dụng mã hóa SSH yếu nhất nhưng nhanh nhất. Phải chỉ định "Mật mã arcfour" trong sshd_config trên đích.
  • o Compression=no: Tắt nén SSH.
  • x: tắt chuyển tiếp X nếu nó được bật theo mặc định.

Thịt bò nằm trong các sshtùy chọn - nếu bạn chỉ sử dụng rsync -av-e ssh -T -c arcfour -o Compression=no -x"một phần, bạn cũng có thể có được những tốc độ này.


So sánh:

  • 13,6 MB / giây rsync -az
  • 16,7 MB / giây scp -Cr
  • 44,8 MB / giây rsync -a
  • 59,8 MB / giây sftp
  • 61,2 MB / s scp -r
  • 61,4 MB / s sftp -R 128 -B 65536
  • 62,4 MB / s rsync -a -P -e "ssh -T -c arcfour -o Compression=no -x"
  • 143,5 MB / giây scp -r -c arcfour
  • 144,2 MB / s sftp -oCiphers=arcfour

Nguồn :

https://gist.github.com/KartikTalwar/4393116

http://nz2nz.blogspot.com/2018/05/rsync-scp-sftp-speed-test.html


3
Chà, dường như chúng đang chạy cp -rtrong hệ thống từ xa, vì vậy mã hóa được sử dụng bởi kết nối SSH không thực sự phù hợp. Trong mọi trường hợp arcfourđược coi là khá hỏng và OpenSSH vô hiệu hóa nó cùng với những người khác trên máy chủ theo mặc định kể từ phiên bản 6.7 (2014-10-06) . Trong mọi trường hợp, ssh -o Ciphers='aes128-ctr'cung cấp cho tôi khoảng 90 MB / s, tốc độ này đủ nhanh trên liên kết 1 Gbit / s.
ilkkachu

Đúng, arcfour đã bị hỏng, nhưng nó không được coi là vỏ AN TOÀN cho trường hợp này, nhưng 'vỏ thoải mái' hơn mà không chú trọng đến mã hóa. Tôi sẽ không sử dụng điều này trên các kết nối không an toàn, điều đó là chính xác. Nếu 'aes128-ctr' đủ nhanh, nó có thể và nên được sử dụng thay thế.
emk2203

Xem thêm câu trả lời mở rộng của tôi để sử dụng với CPU hỗ trợ AES-NI.
emk2203

2

Theo tính toán của tôi, bản sao đầy đủ nhanh nhất luôn sử dụng 'tar' (ở đây giả sử GNU tarhoặc tương thích).

mkdir -p photos2 &&
  tar -C photos -cf - --exclude=./.thumbcache . |
  tar -C photos2 -xpf -

tarcó rất nhiều tùy chọn để thao tác các thuộc tính, quyền và lựa chọn / loại trừ tệp. Ví dụ, lệnh trên không bao gồm thư mục con cấp cao nhất được gọi là .thumbcache trong khi sao chép.


Lưu ý rằng --exclude=.thumbcacheloại trừ tất cả các .thumbcachetệp, không chỉ tệp ở cấp cao nhất. Với GNU tar(không bsdtar), bạn có thể sử dụng --exclude=./.thumbcacheđể chỉ loại trừ .thumbcachetệp cấp cao nhất .
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.