sh再帰コピー(cp -r)-サブフォルダーを除外する方法


8

net / ssh)を使用しsshてリモートスクリプトを実行し、フォルダーを再帰的にコピーしてサブフォルダーを除外する必要があります。私はそれを行う最速の方法を探しているので、良くありません。また、ではなくを使用していることも理解しています。Rubyrsyncsshshbash

バッシュで私はします:

cp -r srcdir/!(subdir) dstdir

そしてそれはうまくいきます。しかし、スクリプトを起動sshするとエラーが表示されます

sh: 1: Syntax error: "(" unexpected

使っているからsh

shmanページを確認しましたが、ファイルを除外するオプションはありません。

それは正しいssh使用の私の仮定shですか?代替案はありますか?

編集1: それが便利な場合、の出力sudo cat /etc/shellsは次のとおりです:

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

編集2: OK。したがって、bashは利用可能であり、それは問題ではないようです。sshが実際に使用していることを確認しましたbash。この問題は、括弧または感嘆符のエスケープに関連しているようです。私はシェル(macos)からコマンドを実行しようとしましたが、これが実際のコマンドです。

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'

このようにして、別のエラーを受け取ります

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

編集3: コメントに基づいて、コマンドを追加して変更しましたextglob

私が使うなら

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'

次のエラーが表示されます。

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

かっこをエスケープしないと、

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

3
ssh(まあsshd)リモートユーザーのログインシェルを使用します。何でもかまいません。
ステファンChazelas

Unixにはフォルダがなく、ディレクトリだけがあります。:)
tchrist

1
このような状況では、リモートホストでスクリプトを開発するだけでよく、1)そのままにしておいて、(必要に応じてプログラムで)sshで実行します。2)毎回変更する場合は、scpで実行します。それをssh経由で削除します。多分追加のステップですが、リモートではなくローカルで拡大する悪夢やグロブをエスケープすることにはなりません。それ以外の場合、@StéphaneChazelasが以下で使用するように、常にヒアドキュメント形式を使用します。
ジョシュランバット

回答:


10

SSHは、リモートシステムでログインシェルを実行します。しかし、!(foo)が必要ですshopt -s extglob。これは、リモートで設定していない可能性があります。

これを試して、SSHがリモート側でBashを実行しているかどうかを確認します。

ssh me@somehost 'echo "$BASH_VERSION"'

何も出力されても起動スクリプトが設定されていないextglob場合は、次のコマンドに渡されたコマンドを手動で実行できますssh

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

extglob コマンドラインの解析に影響し、改行の後にのみ有効になるため、そこにリテラルの改行を配置する必要があります。セミコロンでは不十分です。

ssh me @ somehost 'shopt -s extglob; echo srcdir /!(subdir) '

また、バックスラッシュで括弧をエスケープすると、他のグロブ文字と同様に、それらの特別なプロパティが失われます。これは、この場合に実行したいことではありません。

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

10

rsyncが遅いと思う理由がわかりません。コピーの速度は、主にディスクの速度によって決まります。Rsyncには、含めるものと除外するものを指定する多くのオプションがあるため、シェルグロビングよりもはるかに優れた制御が可能です。

bashマニュアルに記載!(patter)されているように、extglobが設定されている場合のみ、bashで認識されます。あなたの例では、あなたは設定しませんでしたextglob。さらに、bash開始されたままshですがbash、互換性のために一部の拡張機能が無効になります。

で指定されて/etc/passwdいるように、SSHサーバーはユーザーのログインシェルを起動します。シェルを変更するか、そのシェルを使用して、ニーズに合った別のシェルを起動できます。


でテストしましたtimetime cp -r mesh/!(constant) N->実際の1.04秒およびtime rsync -a mesh/ N --exclude=constant->実際の1.8秒
Rojj

7
リンゴとオレンジの比較です。まず、rsyncには-aを使用しますが、cpには使用しません。これには、アクセス許可やその他の属性の保持が含まれるため、実際には同じことをしていません。
ワイルドカード

6

最初にいくつかのメモ:

  • sshサーバーはsh、クライアントから送信されたコマンドラインの解釈を開始せず、リモートホスト上のユーザーのログインシェルをとして実行しますthat-shell -c <the-string-provided-by-the-client>。リモートユーザーのログインシェルは何でもかまいません。のようないくつかのシェルtcshfishまたはのものとrcは非常に異なる構文を持っていることに注意してくださいsh
  • それは実際にはコマンドライン、またはより正確には文字列です(改行文字を含めることができるため、数行になります)。あなたがない場合でもssh host cmd arg1 'arg 2'どこcmdarg1arg 2三つの引数が渡されsshsshスペースでこれらの引数を連結し、実際に送信cmd arg1 arg 2する文字列をsshd、リモートシェルがにそれを分割するだろうcmdarg1arg2
  • !(subdir)glob演算子です(kshglob演算子はzsh -o kshgloband でもサポートされていますbash -O extglob)。すべてのグロブと同様に、隠しファイルを除外するため、除外する他のファイルがあることに注意してください。

ここで、リモートシェルの正しい構文を見つけることによる問題を回避するために、実際に他のシェルに必要なシェルを起動し、stdinを介してコードをフィードするように指示できます(任意の単純な実行方法にリストされているオプションの1つ)リモートユーザーのログインシェルを知らずにsshを介してコマンド?

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

bash -O extglob -O dotglobBourneのようなもの、csh、rc、fishを含むすべての主要なシェルで同じように理解されるコマンドラインです...上記bashがインストールされていてユーザーの$PATH(デフォルト$PATHであり、ユーザーの~/.zshenvfor zsh~/.cshrcfor csh~/.bashrcfor などのログインシェルbash

POSIXly(実際には、bashコマンドよりも多くのシステムにコマンドがあることがわかるかもしれませんpax)、次のようにすることができます。

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

-s転送されるパスに置換を適用します。その置換が何にも拡張されない場合、ファイルは除外されます。問題は、シンボリックリンクのターゲットにも置換が適用されることです。.//.シンボリックリンクが影響を受ける可能性を低くするために上記を使用するのはそのためです。


4

ssh使用に限定されていないと思いますsh。むしろ、ターゲットシステムにインストールされているもの、ユーザーの設定方法、およびで許可されているシェルに依存し /etc/shellsます。

chshコマンドを検討しましたか?


4

高速に実行したい場合rsyncは、別の暗号化アルゴリズムを使用して調べることができます。これにより、あまり速度を犠牲にすることなく、簡単に除外するなどのオプションが提供されます。

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

in でarcfour始まる行に暗号化を追加するとCiphers/etc/ssh/ssh_configまだ有効になっていない場合は、許容可能な速度が得られます。

警告:arcfour暗号化は安全ではありません。安全でないチャネルでこれを実行しないでください。あなたが使用して安全でないチャネルからサーバーへのアクセスを心配している場合はarcfour、暗号化を変更etc/ssh/ssh_configして、ホスト固有のソース・ホストの一部-作成しHost、ソース・ホストのためにあなたはssh_configでセクションを、あなたが使用することができますCiphers arcfour上記ミラーするが-cスイッチを、どのarcfour暗号化をこのホストのみに制限します。

詳細については、ssh_configmanページを参照してください。

ただし、CPUがAES-NI命令セットをサポートしている場合は、aes128-gcm @ openssh.comに切り替えてみてください(そう、@を含む暗号名です)。これは、(AES-NIで)非常に高速なAES128を使用します。 -GCM。

したがって、AES-NIをサポートするCPUを使用"ssh -T -c arcfour -o Compression=no -x"して"ssh -T -c aes128-gcm@openssh.com -o Compression=no -x"、より安全な結果に変更します。

説明

rsync

  • (使用しないでください。-z非常に遅くなります)
  • a:アーカイブモード-再帰的、所有者を保持、権限を保持、変更時間を保持、グループを保持、シンボリックリンクをシンボリックリンクとしてコピー、デバイスファイルを保持。
  • H:ハードリンクを保持します
  • A:ACLを保持します
  • X:拡張属性を保持します
  • x:ファイルシステムの境界を越えない
  • v:詳細度を上げる
  • --numeric-ds:ユーザー/グループ名でuid / gid値をマップしません
  • 同期する必要がある場合は、追加--delete:dest dirsから不要なファイルを削除します(同期中の差分クリーンアップ)
  • --progress:転送中に進行状況を表示

ssh

  • T:pseudo-ttyをオフにして、宛先のCPU負荷を減らします。
  • c arcfour:最も弱いが最も速いSSH暗号化を使用します。宛先のsshd_configで「Ciphers arcfour」を指定する必要があります。
  • o Compression=no:SSH圧縮をオフにします。
  • x:デフォルトでオンになっている場合は、X転送をオフにします。

牛肉はsshオプションにあります-とを使用するだけrsync -avで、-e ssh -T -c arcfour -o Compression=no -x"これらの速度も得ることができます。


比較:

  • 13.6 MB /秒 rsync -az
  • 16.7 MB /秒 scp -Cr
  • 44.8 MB /秒 rsync -a
  • 59.8 MB /秒 sftp
  • 61.2 MB /秒 scp -r
  • 61.4 MB /秒 sftp -R 128 -B 65536
  • 62.4 MB /秒 rsync -a -P -e "ssh -T -c arcfour -o Compression=no -x"
  • 143.5 MB /秒 scp -r -c arcfour
  • 144.2 MB /秒 sftp -oCiphers=arcfour

出典

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

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


3
まあ、それらはcp -rリモートシステム内で実行されているようです。そのため、SSH接続で使用される暗号化はあまり関係がありません。いずれにせよarcfour、かなり壊れていると考えられおり、OpenSSH はバージョン6.7(2014-10-06)以降、サーバー上の他のサーバーとともにデフォルトで無効にしています。いずれの場合でも、ssh -o Ciphers='aes128-ctr'約90 MB / sが得られます。これは、1 Gbit / sリンクで十分高速である必要があります。
ilkkachu

はい、arcfourは壊れていますが、この場合はSECUREシェルではありませんが、暗号化を重視しない、より「快適なシェル」です。安全でない接続ではこれを使用しないでください。「aes128-ctr」が十分速い場合は、代わりに使用でき、使用する必要があります。
emk2203

AES-NIをサポートするCPUでの使用については、私の拡張回答も参照してください。
emk2203

2

私の計算によると、最速のフルコピーは常に「tar」を使用しています(ここではGNU tarまたは互換と想定しています)。

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

またtar、属性、権限、ファイルの選択/除外を操作するためのオプションがたくさんあります。たとえば、上記のコマンドは、コピー中に.thumbcacheと呼ばれる最上位のサブフォルダーを除外します。


は、最上位のファイルだけでなく、すべてのファイルを--exclude=.thumbcache除外することに注意してください.thumbcache。GNUではtar(ではなくbsdtar)、--exclude=./.thumbcacheトップレベルの.thumbcacheファイルのみを除外するために使用できます。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.