scp 用户的 rsync 迁移指南
rsync scp
![](/data/attachment/album/202009/03/102942u7rxf79a7rsr9txz.jpg)


在 [SSH 8.0 预发布公告](https://lists.mindrot.org/pipermail/openssh-unix-dev/2019-March/037672.html)中，OpenSSH 项目表示，他们认为 scp 协议已经过时，不灵活，而且不容易修复，然后他们继而推荐使用 `sftp` 或 `rsync` 来进行文件传输。


然而，很多用户都是从小用着 `scp` 命令长大的，所以对 `rsync` 并不熟悉。此外，`rsync` 可以做的事情也远不止复制文件，这可能会给菜鸟们留下复杂和难以掌握的印象。尤其是，`scp` 命令的标志大体上可以直接对应到 `cp` 命令的标志，而 `rsync` 命令的标志却和它大相径庭。


本文将为熟悉 `scp` 的人提供一个介绍和过渡的指南。让我们跳进最常见的场景：复制文件和复制目录。


### 复制文件


对于复制单个文件而言，`scp` 和 `rsync` 命令实际上是等价的。比方说，你需要把 `foo.txt` 传到你在名为 `server` 的服务器上的主目录下：



```
$ scp foo.txt me@server:/home/me/

```

相应的 `rsync` 命令只需要输入 `rsync` 取代 `scp`：



```
$ rsync foo.txt me@server:/home/me/

```

### 复制目录


对于复制目录，就有了很大的分歧，这也解释了为什么 `rsync` 会被认为比 `scp` 更复杂。如果你想把 `bar` 目录复制到 `server` 服务器上，除了指定 `ssh` 信息外，相应的 `scp` 命令和 `cp` 命令一模一样。



```
$ scp -r bar/ me@server:/home/me/

```

对于 `rsync`，考虑的因素比较多，因为它是一个比较强大的工具。首先，我们来看一下最简单的形式：



```
$ rsync -r bar/ me@server:/home/me/

```

看起来很简单吧？对于只包含目录和普通文件的简单情况，这就可以了。然而，`rsync` 更在意发送与主机系统中一模一样的文件。让我们来创建一个稍微复杂一些，但并不罕见的例子：



```
# 创建多级目录结构
$ mkdir -p bar/baz
# 在其根目录下创建文件
$ touch bar/foo.txt
# 现在创建一个符号链接指回到该文件
$ cd bar/baz
$ ln -s ../foo.txt link.txt
# 返回原位置
$ cd -

```

现在我们有了一个如下的目录树：



```
bar
├── baz
│   └── link.txt -> ../foo.txt
└── foo.txt

1 directory, 2 files

```

如果我们尝试上面的命令来复制 `bar`，我们会注意到非常不同的（并令人惊讶的）结果。首先，我们来试试 `scp`：



```
$ scp -r bar/ me@server:/home/me/

```

如果你 `ssh` 进入你的服务器，看看 `bar` 的目录树，你会发现它和你的主机系统有一个重要而微妙的区别：



```
bar
├── baz
│   └── link.txt
└── foo.txt

1 directory, 2 files

```

请注意，`link.txt` 不再是一个符号链接，它现在是一个 `foo.txt` 的完整副本。如果你习惯于使用 `cp`，这可能会是令人惊讶的行为。如果你尝试使用 `cp -r` 复制 `bar` 目录，你会得到一个新的目录，里面的符号链接和 `bar` 的一样。现在如果我们尝试使用之前的 `rsync` 命令，我们会得到一个警告：



```
$ rsync -r bar/ me@server:/home/me/
skipping non-regular file "bar/baz/link.txt"

```

`rsync` 警告我们它发现了一个非常规文件，并正在跳过它。因为你没有告诉它可以复制符号链接，所以它忽略了它们。`rsync` 在手册中有一节“符号链接”，解释了所有可能的行为选项。在我们的例子中，我们需要添加 `-links` 标志：



```
$ rsync -r --links bar/ me@server:/home/me/

```

在远程服务器上，我们看到这个符号链接是作为一个符号链接复制过来的。请注意，这与 `scp` 复制符号链接的方式不同。



```
bar/
├── baz
│   └── link.txt -> ../foo.txt
└── foo.txt

1 directory, 2 files

```

为了省去一些打字工作，并利用更多的文件保护选项，在复制目录时可以使用归档标志 `-archive`（简称 `-a`）。该归档标志将做大多数人所期望的事情，因为它可以实现递归复制、符号链接复制和许多其他选项。



```
$ rsync -a bar/ me@server:/home/me/

```

如果你感兴趣的话，`rsync` 手册页有关于存档标志的深入解释。


### 注意事项


不过，使用 `rsync` 有一个注意事项。使用 `scp` 比使用 `rsync` 更容易指定一个非标准的 ssh 端口。例如，如果 `server` 使用 8022 端口的 SSH 连接，那么这些命令就会像这样：



```
$ scp -P 8022 foo.txt me@server:/home/me/

```

而在使用 `rsync` 时，你必须指定要使用的“远程 shell”命令，默认是 `ssh`。你可以使用 `-e` 标志来指定。



```
$ rsync -e 'ssh -p 8022' foo.txt me@server:/home/me/

```

`rsync` 会使用你的 `ssh` 配置；但是，如果你经常连接到这个服务器，你可以在你的 `~/.ssh/config` 文件中添加以下代码。这样你就不需要再为 `rsync` 或 `ssh` 命令指定端口了！



```
Host server
    Port 8022

```

另外，如果你连接的每一台服务器都在同一个非标准端口上运行，你还可以配置 `RSYNC_RSH` 环境变量。


### 为什么你还是应该切换到 rsync？


现在我们已经介绍了从 `scp` 切换到 `rsync` 的日常使用案例和注意事项，让我们花一些时间来探讨一下为什么你可能想要使用 `rsync` 的优点。很多人在很久以前就已经开始使用 `rsync` 了，就是因为这些优点。


#### 即时压缩


如果你和服务器之间的网络连接速度较慢或有限，`rsync` 可以花费更多的 CPU 处理能力来节省网络带宽。它通过在发送数据之前对数据进行即时压缩来实现。压缩可以用 `-z` 标志来启用。


#### 差量传输


`rsync` 也只在目标文件与源文件不同的情况下复制文件。这可以在目录中递归地工作。例如，如果你拿我们上面的最后一个 `bar` 的例子，并多次重新运行那个 `rsync` 命令，那么在最初的传输之后就不会有任何传输。如果你知道你会重复使用这些命令，例如备份到 U 盘，那么使用 `rsync` 即使是进行本地复制也是值得的，因为这个功能可以节省处理大型数据集的大量的时间。


#### 同步


顾名思义，`rsync` 可以做的不仅仅是复制数据。到目前为止，我们只演示了如何使用 `rsync` 复制文件。如果你想让 `rsync` 把目标目录变成源目录的样子，你可以在 `rsync` 中添加删除标志 `-delete`。这个删除标志使得 `rsync` 将从源目录中复制不存在于目标目录中的文件，然后它将删除目标目录中不存在于源目录中的文件。结果就是目标目录和源目录完全一样。相比之下，`scp` 只会在目标目录下添加文件。


### 结论


对于简单的使用情况，`rsync` 并不比老牌的 `scp` 工具复杂多少。唯一显著的区别是在递归复制目录时使用 `-a` 而不是 `-r`。然而，正如我们看到的，`rsync` 的 `-a` 标志比 `scp` 的 `-r` 标志更像 `cp` 的 `-r` 标志。


希望通过这些新命令，你可以加快你的文件传输工作流程。




---


via: <https://fedoramagazine.org/scp-users-migration-guide-to-rsync/>


作者：[chasinglogic](https://fedoramagazine.org/author/chasinglogic/) 选题：[lujun9972](https://github.com/lujun9972) 译者：[wxy](https://github.com/wxy) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
As part of the[ 8.0 pre-release announcement,](https://lists.mindrot.org/pipermail/openssh-unix-dev/2019-March/037672.html) the OpenSSH project stated that they consider the scp protocol outdated, inflexible, and not readily fixed. They then go on to recommend the use of sftp or rsync for file transfer instead.

Many users grew up on the *scp *command, however, and so are not familiar with rsync. Additionally, rsync can do much more than just copy files, which can give a beginner the impression that it’s complicated and opaque. Especially when broadly the scp flags map directly to the cp flags while the rsync flags do not.

This article will provide an introduction and transition guide for anyone familiar with scp. Let’s jump into the most common scenarios: Copying Files and Copying Directories.

## Copying files

For copying a single file, the scp and rsync commands are effectively equivalent. Let’s say you need to ship *foo.txt* to your home directory on a server named *server.*

$ scp foo.txt me@server:/home/me/

The equivalent rsync command requires only that you type rsync instead of scp:

$ rsync foo.txt me@server:/home/me/

## Copying directories

For copying directories, things do diverge quite a bit and probably explains why rsync is seen as more complex than scp. If you want to copy the directory *bar *to *server* the corresponding scp command looks exactly like the cp command except for specifying ssh information:

$ scp -r bar/ me@server:/home/me/

With rsync, there are more considerations, as it’s a more powerful tool. First, let’s look at the simplest form:

$ rsync -r bar/ me@server:/home/me/

Looks simple right? For the simple case of a directory that contains only directories and regular files, this will work. However, rsync cares a lot about sending files exactly as they are on the host system. Let’s create a slightly more complex, but not uncommon, example.

# Create a multi-level directory structure $ mkdir -p bar/baz # Create a file at the root directory $ touch bar/foo.txt # Now create a symlink which points back up to this file $ cd bar/baz $ ln -s ../foo.txt link.txt # Return to our original location $ cd -

We now have a directory tree that looks like the following:

bar ├── baz │ └── link.txt -> ../foo.txt └── foo.txt 1 directory, 2 files

If we try the commands from above to copy bar, we’ll notice very different (and surprising) results. First, let’s give scp a go:

$ scp -r bar/ me@server:/home/me/

If you ssh into your server and look at the directory tree of bar you’ll notice an important and subtle difference from your host system:

bar ├── baz │ └── link.txt └── foo.txt 1 directory, 2 files

Note that *link.txt* is no longer a symlink. It is now a full-blown copy of *foo.txt*. This might be surprising behavior if you’re used to *cp*. If you did try to copy the *bar* directory using *cp -r*, you would get a new directory with the exact symlinks that *bar* had. Now if we try the same rsync command from before we’ll get a warning:

$ rsync -r bar/ me@server:/home/me/ skipping non-regular file "bar/baz/link.txt"

Rsync has warned us that it found a non-regular file and is skipping it. Because you didn’t tell it to copy symlinks, it’s ignoring them. Rsync has an extensive manual section titled “SYMBOLIC LINKS” that explains all of the possible behavior options available to you. For our example, we need to add the –links flag.

$ rsync -r --links bar/ me@server:/home/me/

On the remote server we see that the symlink was copied over as a symlink. Note that this is different from how scp copied the symlink.

bar/ ├── baz │ └── link.txt -> ../foo.txt └── foo.txt 1 directory, 2 files

To save some typing and take advantage of more file-preserving options, use the –archive (-a for short) flag whenever copying a directory. The archive flag will do what most people expect as it enables recursive copy, symlink copy, and many other options.

$ rsync -a bar/ me@server:/home/me/

The rsync man page has in-depth explanations of what the archive flag enables if you’re curious.

## Caveats

There is one caveat, however, to using rsync. It’s much easier to specify a non-standard ssh port with scp than with rsync. If *server *was using port 8022 SSH connections, for instance, then those commands would look like this:

$ scp -P 8022 foo.txt me@server:/home/me/

With rsync, you have to specify the “remote shell” command to use. This defaults to *ssh*. You do so using the* *-e flag.

$ rsync -e 'ssh -p 8022' foo.txt me@server:/home/me/

Rsync does use your ssh config; however, so if you are connecting to this server frequently, you can add the following snippet to your *~/.ssh/config* file. Then you no longer need to specify the port for the rsync or ssh commands!

Host server Port 8022

Alternatively, if every server you connect to runs on the same non-standard port, you can configure the *RSYNC_RSH* environment variable.

## Why else should you switch to rsync?

Now that we’ve covered the everyday use cases and caveats for switching from scp to rsync, let’s take some time to explore why you probably want to use rsync on its own merits. Many people have made the switch to rsync long before now on these merits alone.

### In-flight compression

If you have a slow or otherwise limited network connection between you and your server, rsync can spend more CPU cycles to save network bandwidth. It does this by compressing data before sending it. Compression can be enabled with the -z flag.

### Delta transfers

Rsync also only copies a file if the target file is different than the source file. This works recursively through directories. For instance, if you took our final bar example above and re-ran that rsync command multiple times, it would do no work after the initial transfer. Using rsync even for local copies is worth it if you know you will repeat them, such as backing up to a USB drive, for this feature alone as it can save a lot of time with large data sets.

### Syncing

As the name implies, rsync can do more than just copy data. So far, we’ve only demonstrated how to copy files with rsync. If you instead want rsync to make the target directory look like your source directory, you can add the –delete flag to rsync. The delete flag makes it so rsync will copy files from the source directory which don’t exist on the target directory. Then it will remove files on the target directory which do not exist in the source directory. The result is the target directory is identical to the source directory. By contrast, scp will only ever add files to the target directory.

## Conclusion

For simple use cases, rsync is not significantly more complicated than the venerable scp tool. The only significant difference being the use of -a instead of -r for recursive copying of directories. However, as we saw rsync’s -a flag behaves more like cp’s -r flag than scp’s -r flag does.

Hopefully, with these new commands, you can speed up your file transfer workflow!

## Henrique

This post is missing the difference between dir/ and dir when copying directories, and the actual examples are wrong, as using dir/ will only copy the directory contents, but not the directory itself.

## Mohammed El-Afifi

Indeed.

## Daniel

The section on delta transfers misses that you need an extra flag to enable it on local transfers. I think but don’t remember for sure that it’s –no-whole-file.

## chasinglogic

Hey Daniel, rsync will not copy files that already exist even locally without the –no-whole-file option.

I use –archive in my backup scripts to personal drives but not the –no-whole-file option and observe this behavior.

–whole-file disables the delta transfer algorithim and –no-whole-file overwrites previous uses of –whole-file on the command line to turn it back on. –whole-file is not the default but can be implied by other options you may use that require you to pass –no-whole file.

## Sébastien Wilmet

I think it would be possible to implement the scp interface (or a subset of it) on top of rsync. So without using the scp protocol, but just having a wrapper around the rsync command.

## Sebastiaan Franken

You can do that with a shell alias as far as I know. Something like “alias scp=’rsync -a’ ” in your .bashrc (or .zshrc, or whatever). Once you source the file (source ~/.bashrc, or login again) scp will not call the actual scp binary but rsync with the -a option.

## X

Modifying sftp to act like scp would fix the issue, and be a welcome update. Currently, a batch file has to be written to get sftp to work without interaction. Rebasing scp on sftp is probably something that should have been done years ago.

## Carrete

I use this:

#!/usr/bin/env bash

rsync --archive --partial --progress --rsh=ssh "$@"

This works for local and remote transfers.

## Vernon Van Steenkist

Not sure why you were using scp if sftp is available. Simply put the URL

sftp://me@server:/home/me/

in your file manager directory window and you get a VFS where you can easily copy, paste, edit, play, etc remote files with your file manager.

For even more flexibility, use sshfs

mkdir home

sshfs me@server:/home/me home

and now you have a mounted remote file system at sub-directory me through sftp that any program can interact with directly.

From a terminal, mc (Midnight Commander) supports sftp virtual file systems as well.

I agree that using rsync is great for syncing photo directories etc. But for more simple copy and paste operations, I find sftp easier and more flexible – especially paired with a graphical file manager or sshfs.

Note that if you move files and directories around, you may want to add –delete to your rsync command. Otherwise, your destination can become filled with cruft.

## jtad

good advice. but sshfs is much slower than nfs due to encryption

## Charlie

Can I ask a stupid question?

Why can’t ssh formally do this:

C:\bin>pscp -h

PuTTY Secure Copy client

Release 0.72

..,

-sftp force use of SFTP protocol

-scp force use of SCP protocol

Why are we having this conversation again?

## Jim

This may well work, a lot of us just don’t have Windows.

## Shy

https://gist.github.com/xiaowl/3075638

Pure python implementation of

, using SFTP protocol. Depends on paramiko.

## X

It should be mentioned rsync needs to be installed on the source and destination systems. Some systems don’t install rsync by default, and it will throw an odd message when it fails to start a remote rsync process. This trips me up on occasion. 🙂

## Rob N

It is only required on the system from which the rsync command is run.

## Moritz

rsync doesn’t need to be installed on the opposite system, an ssh with a proper scpserver implementation suffices, and that is the case on most desktop and server openssh based installations (but often not on embedded devices, such as STBs, PVRs).

## Robin A. Meade

The rsync man page ( https://download.samba.org/pub/rsync/rsync.1 ) says

If I attempt to rsync to a server without rsync installed, I receive the following error message:

bash: rsync: command not found

## sitaram

I am pretty sure this command:

does NOT produce the output you showed subsequently; i.e., the “bar” directory itself being copied to the remote.

Makes me wonder, did you even try the examples you showed.

## Bruno Haible

rsync does not do encryption. Therefore anyone who uses rsync is vulnerable to man-in-the-middle attacks. Thus the only place where rsync, on its own, can be securely used is a small LAN.

Other than that, rsync can be combined with ssh or a VPN, to make it secure.

So, anyone who recommends plain rsync as a replacement of scp has not been thinking about security.

## Rob N

By default rsync uses ssh if you are using the scp syntax “user@host:”

## Bruno

By saying scp is “outdated, inflexible, and not readily fixed”, does that mean it is insecure in any way? Besides other advantages of rsync, should I stop using scp for security reasons?

In scripts I’ve been using rsync as it is indeed more flexible, but on interactive shell for simple operations I often use scp because it is analog to cp.

## Christopher Cox

Another ssh option, if you have reasonably contemporary machinery and reasonably new ssh is “-c aes128-gcm@openssh.com” as this will leverage the AES-NI instructions on the CPU. The results are quite staggering.

## Frank

how about aes256-gcm@openssh.com?

## Eduard Lucena

Also, I would comment how sensitive is rsync to directions. It’s no the same to do

rsync foo server:/bar

than

rsync foo/ server:/Bar

## Alberto Patino

Nice article! I did not know that scp is outdated. I have used rsync occasionally, indeed, it is a great tool. I know sometimes it is harder to get acquainted to rsync, but after read pre release notes I think I’ll be happy to use rsync instead of scp.

Honestly, I’ve used rsync for bulk data transfers and scp just to copy one or few files. It was a matter of convenience, so I’ll say goodbye to scp.

## Marcelo Mafra

Updated my system yesterday and rsync got update from 3.1.3 to 3.2.2.

It is receiving updates after 2 two years, maybe we can ask for the caveat of ssh to be addressed somehow.

Maybe an alias:

rsync -w 8022 foo.txt me@server:/home/me/

–ssh-custom-port, –ssh-port, –ssh, -w

This option is an alias for -e ‘ssh -p ‘.

rsync -w 2234 [SOURCE] [user@]host:[DEST]

There is a version 3.2.3 to be released.

https://download.samba.org/pub/rsync/NEWS

## Mark

On the mention of in flight compression. SCP has the option “-C” which does the same thing, so compression to minimise network traffic is not a valid reason to switch to rsync as scp provides the same facility.

As already mentioned rsync traffic is not encrypted so should never be used anywhere except on an internal physically cabled local network.

A benefit of SCP is that SCP uses ssh keys, so can be used for hands-off (no password prompt) secure copying of individual files.

rsync certainly has it’s uses if you need to keep entire directories in sync in a local environment between two machines, so thanks for this post.

## Nehemiah I. Dacres

How are we going to work with remote systems where local shell access is not available? Web Hosting providers don’t give shell access so we can’t rsync and sftp isn’t recursive.

## Theodore Cowan

I’m skeptical of this post. Calling SCP outmoded over a resolved CVE? scp has had lasting power for a reason.

## Daniel Martin

If the SCP

protocolis outdated, surely that simply means that the implementation of thecommandshould be changed to use the sftp protocol in its place.I don’t see why changing protocols should stop us from using a nice simple and intuitive interface,

## Cody

As a programmer I couldn’t disagree more.

You’re asking for trouble. Not only will that cause compatibility problems it will also cause major confusion. ‘I upgraded and now it’s doing something else!’ No. Bad, bad, bad idea. Very bad idea.

You don’t change the implementation of something like that. Also sftp is different from scp so why would you change the scp command to implement the sftp? As I recall they even use different ports so firewalls would have to be changed too.

There are other reasons that your suggestion is terrible. I don’t mean to be unkind about it but it really is a bad idea for so many reasons and some of the most important ones I just listed.

## Daniel Martin

So just throw it away entirely, and force people to use something less intuitive? Can’t you see that is even worse?

Breaking changes happen in software, changing the underlying protocol of the tool would be such a breaking change. You could do everything in your power to inform sysadmins of the change so that they can adapt to it. Possibly you would only upgrade to the new version in a new version of a distro such as Fedora.

## Ralph Grothe

One thing that I didn’t like so much about sftp, if my memory serves me correctly, was that in older versions (e.g. say on RHEL6 hosts) it lacked the -i option, where to use key based authentication you had to type something like

e.g.

scp -o identityfile=~/.ssh/my_rsa_id …

Also the usage of a batch file

(ok, using -b – you could pipe into sftp or read from a herestring some batch commands)

was a bit awkward in scripting.

As for rsync, I would like to know if rsync would honour any ssh_config option of the ssh client as documented in the ssh_config manpage that you would feed by

e.g. rsync -e ‘ssh -o opt1 -o opt2 … -o optN’ …

## SeeM

Thanks. I use -e for tunneling also:

rsync -[various_options] -e “ssh -p 1234” /dir/ user@localhost:/dir/

## Cody

There’s another caveat and one that you really should have covered. Let me rephrase that: you

reallyshould have covered it. Here – I’ll help by including what’s in the manpage:this directory" as opposed to "copy the directory by name", but in both cases the attributes of the containing directory are transferred to the containing directory on the destination. In other

words, each of the following commands copies the files in the same way, including their setting of the attributes of /dest/foo:

rsync -av /src/foo /dest

rsync -av /src/foo/ /dest/foo

Not knowing this can cause a lot of confusion and directories with files that you intended to be in a subdirectory rather than in the current working directory! You really ought to point this out. It will cause a lot of grief to people! You might also want to point out the dryrun option? If that was used some users might be able to pick up on the problem I described

beforeit’s too late!…Of course you could always use ssh itself to copy files over e.g. with the pipe tricks. But never mind that.

## Cody

…and of course the formatting got messed up in my previous post. Typical.