web-dev-qa-db-ja.com

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

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

バッシュで私はします:

cp -r srcdir/!(subdir) dstdir

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

sh: 1: Syntax error: "(" unexpected

shを使用しているためです。

shのマニュアルページを確認しましたが、ファイルを除外するオプションがありません。

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

EDIT 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 [email protected] '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

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

私が使うなら

ssh -i .ssh/key.pem [email protected] '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 `('
8
Rojj

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
ilkkachu

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

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

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

10
RalfFriedl

最初にいくつかのメモ:

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

ここでは、リモートシェルの正しい構文を見つけることによる問題を回避するために、実際に他のシェルに必要なシェルを起動して、stdin( How toリモートユーザーのログインシェルを知らずにsshで任意の簡単なコマンドを実行しますか?

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

bash -O extglob -O dotglobは、Bourne系のシェル、csh、rc、fishな​​ど、すべての主要なシェルで同じように理解されるコマンドラインです。上記は、bashがインストールされ、ユーザーの$PATHにある限り機能します。 (デフォルトの$PATHzshの場合は~/.zshenvcshの場合は~/.cshrcbashの場合は~/.bashrcなど、ユーザーのログインシェルによって変更される可能性があります)。

POSIXly(実際には、より多くのシステムがbashコマンドよりもpaxコマンドを持っていることに気付くかもしれません)、あなたはそうすることができます:

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

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

6

sshshの使用に限定されているとは思いません。ターゲットシステムに何がインストールされているか、ユーザーがどのように設定されているか、/etc/shellsで許可されているシェルに依存します。

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

4
RudiC

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

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

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

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

詳細については、ssh_configのマニュアルページを参照してください。

ただし、CPUがAES-NI命令セットをサポートしている場合は、aes128-gcm @ openssh.com(つまり、@を含む暗号名)に切り替えてみてください。 -GCM。

したがって、CPUがAES-NIをサポートしている場合、"ssh -T -c arcfour -o Compression=no -x""ssh -T -c [email protected] -o Compression=no -x"に変更すると、より安全な結果が得られます。

説明

rsync

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

ssh

  • T:疑似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

4
emk2203

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

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

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

2
Lam Das