比较:

比较:

我需要使用sshvia Ruby(网络/SSH) 递归复制文件夹并排除子文件夹。我正在寻找最快的方法来做到这一点,所以rsync不好。另外,我知道ssh使用sh而不是bash

在 bash 中我这样做:

cp -r srcdir/!(subdir) dstdir

而且效果很好。但是,当我通过启动脚本时ssh收到错误

sh: 1: Syntax error: "(" unexpected

因为它正在使用sh.

我已经检查了sh手册页,但没有排除文件的选项。

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: 好的。所以 bash 是可用的,这似乎不是问题。我已经验证 ssh 实际上正在使用bash.该问题似乎与括号或感叹号的转义有关。我尝试从 shell (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

编辑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 `('

答案1

SSH 在远程系统上运行您的登录 shell,无论远程系统是什么。但!(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/!(子目录)'

同样,如果您用反斜杠转义括号,它们也会像任何其他全局字符一样失去其特殊属性。在这种情况下,这不是您想要做的。

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

答案2

我不知道为什么你认为 rsync 会很慢。复制的速度主要取决于磁盘的速度。 Rsync 有很多选项来指定您想要包含和排除的内容,因此它为您提供了比 shell 通配符更好的控制。

正如 bash 手册所述,只有设置后,!(patter)bash 才能识别。extglob在你的例子中你没有设置extglob.此外,a仍然bash按原样启动,但会禁用某些扩展以实现兼容性。shbash

SSH 服务器将启动用户的登录 shell,如 中指定的/etc/passwd。您可以更改 shell,或者使用该 shell 启动另一个更适合您需求的 shell。

答案3

首先有一些注意事项:

  • ssh 服务器不会开始sh解释客户端发送的命令行,它会在远程主机上运行用户的登录 shell,如that-shell -c <the-string-provided-by-the-client>.远程用户的登录 shell 可以是任何东西。请记住,某些 shell 的语法类似于或tcsh与的语法非常不同。fishrcsh
  • 它实际上是一个命令行,或更确切地说是一个字符串(可以包含换行符,所以有几行)。即使您执行ssh host cmd arg1 'arg 2'where cmdarg1andarg 2是传递给 的三个参数sshssh也会将这些参数与空格连接起来并实际将cmd arg1 arg 2字符串发送到sshd,远程 shell 会将其拆分为cmdarg1和。arg2
  • !(subdir)是一个 glob 运算符(andksh也支持 glob 运算符)。与所有 glob 一样,它排除隐藏文件,因此请注意它可能排除其他文件。zsh -o kshglobbash -O extglob

在这里,为了避免找到远程 shell 的正确语法的问题,您实际上可以告诉其他 shell 启动您想要的 shell,并通过 stdin 向其提供代码(在如何在不知道远程用户的登录 shell 的情况下通过 ssh 执行任意简单命令?

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

bash -O extglob -O dotglob是所有主要 shell 都可以理解的命令行,包括类似 Bourne 的 shell、csh、rc、fish...只要bash安装并位于用户的$PATH(默认$PATH,可能由用户的修改)中,上面的内容就可以工作登录 shell 类似于~/.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

如果你想以更快的方式做到这一点,你可以考虑rsync使用不同的加密算法。这使您可以选择轻松排除等,而不会牺牲太多速度。

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

加上将加密添加到以inarcfour开头的行(如果尚未启用),将为您提供可接受的速度。Ciphers/etc/ssh/ssh_config

警告:arcfour加密是不安全感。不要通过不安全的渠道运行此程序。如果您担心使用arcfour加密从不安全的通道访问服务器,请etc/ssh/ssh_config使用特定于宿主的源主机的部分 -Host在 ssh_config 中为源主机创建一个部分,您可以使用Ciphers arcfour它来镜像上述-c开关,该arcfour开关仅将加密限制到该主机。

有关详细信息,请参阅ssh_config手册页。

但是,如果您的 CPU 支持 AES-NI 指令集,请尝试切换到[电子邮件受保护](是的,这就是密码名称,包括 @ 内容),它将使用速度极快(使用 AES-NI)的 AES128-GCM。

因此,如果 CPU 支持 AES-NI,请更改"ssh -T -c arcfour -o Compression=no -x"为以获得更安全的结果。"ssh -T -c [email protected] -o Compression=no -x"

解释

同步

  • (不要使用-z,速度慢得多)
  • a:存档模式 - 递归,保留所有者,保留权限,保留修改时间,保留组,将符号链接复制为符号链接,保留设备文件。
  • H:保留硬链接
  • A:保留 ACL
  • X:保留扩展属性
  • x:不要跨越文件系统边界
  • v: 增加详细程度
  • --numeric-ds:不要按用户/组名称映射 uid/gid 值
  • 如果需要同步,请添加--delete:从目标目录中删除无关文件(同步期间进行差异清理)
  • --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.6MB/秒 rsync -az
  • 16.7MB/秒 scp -Cr
  • 44.8MB/秒 rsync -a
  • 59.8MB/秒 sftp
  • 61.2MB/秒 scp -r
  • 61.4MB/秒 sftp -R 128 -B 65536
  • 62.4MB/秒 rsync -a -P -e "ssh -T -c arcfour -o Compression=no -x"
  • 143.5MB/秒 scp -r -c arcfour
  • 144.2MB/秒 sftp -oCiphers=arcfour

来源:

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

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

相关内容