Skip to main content

如何在远程服务器上用SFTP安全地传输文件

作者 Justin Ellingwood

导语

FTP(File Transfer Protocol),即文件传输协议,是一种在两个系统之间不加密传输文件的方法,曾一度很流行。然而时至今日,由于缺乏安全性,这种方法已被大多数现代软件弃用,几乎只出现在遗留应用程序中。

SFTP(Secure File Transfer Protocol),即安全文件传输协议,是一种内置于SSH中的协议,可以通过安全的连接实现FTP命令。一般来说,如果程序还需要用到FTP,可以直接用SFTP代替。

在几乎所有情况下,SFTP都比FTP更可取,因为它更具安全性,还可以搭载SSH连接。而FTP并不安全,只能在少数情况下或是受信任的网络中使用。

尽管SFTP已被集成到了许多图形工具中,本教程还是会在SFTP的交互式命令行界面中演示如何使用它。

如何连接SFTP

默认情况下,SFTP使用SSH协议进行身份验证和建立安全连接。因此,可以使用与SSH相同的验证方法。

虽然SSH默认用密码验证,但推荐创建SSH密钥,并将公钥传输到所有需要访问的系统中。这样更加安全,而且长远来说更省时间。

如果您可以用SSH连接到计算机,就已经满足了所有用SFTP管理文件所需的条件。使用以下命令测试SSH访问:

ssh sammy@your_server_ip_or_remote_hostname

如果该命令成功运行,可以输入以下命令退出:

$ exit

现在,可以用以下命令创建SFTP会话:

sftp sammy@your_server_ip_or_remote_hostname

这样即可连接至远程系统,提示符也会变为SFTP提示符。

如果您使用的是自定义SSH端口(非默认的22号端口),可以用以下命令创建SFTP会话:

sftp -oPort=custom_port sammy@your_server_ip_or_remote_hostname

这会将您通过指定端口连接至远程服务器。

在SFTP中打开帮助页面

最有用的,也是应最先学习的命令就是help命令。通过这条命令,您可以查阅其它SFTP命令的摘要。在提示符后任选以下两个命令中的一个输入,即可访问帮助页面:

sftp> help

或是

sftp> ?

可用命令列表就会出现:

Output

Available commands:
bye Quit sftp
cd path Change remote directory to 'path'
chgrp grp path Change group of file 'path' to 'grp'
chmod mode path Change permissions of file 'path' to 'mode'
chown own path Change owner of file 'path' to 'own'
df [-hi] [path] Display statistics for current directory or
filesystem containing 'path'
exit Quit sftp
get [-Ppr] remote [local] Download file
help Display this help text
lcd path Change local directory to 'path'
. . .

后续部分将会深入介绍其中的一部分命令。

通过SFTP浏览

有许多命令可以用来浏览远程系统的文件层次机构。这些命令在shell中都有对应,且功能也类似。

首先,找出目前所在远程系统目录位置来定位自己。与在典型shell会话中类似,可以输入以下命令获取当前位置:

sftp> pwd
Output

Remote working directory: /home/demouser

通过另一个熟悉的指令,可以查看远程系统当前目录中的内容:

sftp> ls
Output
Summary.txt info.html temp.txt testDirectory

值得注意的是,SFTP界面中的可用命令与shell的典型语法并非一模一样,命令功能也并不丰富。但它们提供了一些更重要的可选标记,例如在 ls 后添加 -la,用来查看更多文件的元数据和权限:

sftp> ls -la
Output

drwxr-xr-x 5 demouser demouser 4096 Aug 13 15:11 .
drwxr-xr-x 3 root root 4096 Aug 13 15:02 ..
-rw------- 1 demouser demouser 5 Aug 13 15:04 .bash_history
-rw-r--r-- 1 demouser demouser 220 Aug 13 15:02 .bash_logout
-rw-r--r-- 1 demouser demouser 3486 Aug 13 15:02 .bashrc
drwx------ 2 demouser demouser 4096 Aug 13 15:04 .cache
-rw-r--r-- 1 demouser demouser 675 Aug 13 15:02 .profile
. . .

使用以下命令切换目录:

sftp> cd testDirectory

以上命令可以用来遍历远程文件系统。而当需要访问本地文件系统时,可以通过在命令前加 l 表示导向本地。

所有目前出现过的命令都有导向本地的版本。例如,可以用以下命令print本地工作目录:

sftp> lpwd
Output

Local working directory: /Users/demouser

可以用以下命令列出本地机器当前目录中的内容:

sftp> lls
Output

Desktop local.txt test.html
Documents analysis.rtf zebra.html

还可以更改想用的本地系统目录:

sftp> lcd Desktop

用SFTP传输文件

若需要从远程主机下载文件,可以用 get 命令:

sftp> get remoteFile
Output

Fetching /home/demouser/remoteFile to remoteFile
/home/demouser/remoteFile 100% 37KB 36.8KB/s 00:01

从上面可以看出,默认情况下,get 命令会将远程文件下载至本地文件系统里的同名文件中。

我们可以在以上命令后指定一个名称,用另一个名字复制远程文件:

sftp> get remoteFile localFile

get 命令后还可以添加标记。比如,通过指定递归选项,可以复制一个目录及其内部的所有内容。

sftp> get -r someDirectory

还可以用 -P-p 标记使SFTP维持适当的权限和访问时间:

sftp> get -Pr someDirectory

将本地文件传输至远程系统

传输本地文件至远程系统的方法与从远程系统下载文件类似,但要使用 put 命令:

sftp> put localFile
Output

Uploading localFile to /home/demouser/localFile
localFile 100% 7607 7.4KB/s 00:00

get 后可以加的标记同样能用在 put 后。所以可以用 put -r 复制整个本地目录:

sftp> put -r localDirectory

df 命令的作用与自己的命令行版本类似,在下载与上传文件时十分有用。用这个命令可以检查是否有足够的空间来完成您想要进行的传输:

Output
Size Used Avail (root) %Capacity
19.9GB 1016MB 17.9GB 18.9GB 4%

注意,这条命令没有本地版本,但可以用 ! 命令解决。! 命令将会打开一个本地shell,在这个shell中,我们可以对本地系统运行任何可用的命令。可以用以下命令检查磁盘的使用情况:

sftp> !

$ df -h
Output

Filesystem Size Used Avail Capacity Mounted on
/dev/disk0s2 595Gi 52Gi 544Gi 9% /
devfs 181Ki 181Ki 0Bi 100% /dev
map -hosts 0Bi 0Bi 0Bi 100% /net
map auto_home 0Bi 0Bi 0Bi 100% /home

其它的本地指令也会按预期运行。而输入以下命令即可回到 SFTP 会话:

$ exit

这时,您应该可以看到SFTP提示符再次出现了。

用SFTP进行简单文件操作

SFTP支持某些类型的文件系统管理。例如,使用以下命令可以改变远程系统中文件的所有者:

sftp> chown userID file

值得注意的是,与系统 chmod 命令不同,SFTP只接受UID,而不是用户名。然而,没有内置方法可以从SFTP接口中知道适当的UID。

作为替代方案,可以从 /etc/passwd 文件中获取UID。大多数Linux环境中,这个文件将用户名与UID关联:

sftp> get /etc/passwd
sftp> !less passwd
Output

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
. . .

注意,此处并不是用 ! 命令本身,而是将它作为本地shell命令的前缀。这样,我们就可以在本地机器上运行所有可用的命令。而在之前的例子中,这个前缀也可以和本地 df 命令一起使用。

UID位于文件第三列,由冒号字符表示。

类似地,可用以下命令改变文件的组拥有者:

sftp> chgrp groupID file

同样,没有内置方法可以获取远程系统组的列表。对此,我们可以使用以下命令解决:

sftp> get /etc/group
sftp> !less group
Output

root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
. . .

第三列中有和第一列中名字相关联的组的ID,这正是我们想要的。

chmod SFTP命令在远程文件系统上照常运行:

sftp> chmod 777 publicFile
Output

Changing mode on /home/demouser/publicFile

并没有等价的命令能设置本地文件的权限,但可以设置本地umask,使所有被复制进本地系统的文件都有对应的权限。

可以用 lumask 命令完成这一步:

sftp> lumask 022

Output

Local umask: 022

现在,下载的全部常规文件(只要没有用过 -p 标记)都有644项权限了。

SFTP还支持在本地和远程系统中用 lmkdirmkdir 分别创建目录。

而其余文件命令仅对远程文件系统生效:

sftp> ln
sftp> rm
sftp> rmdir

这些命令重复了它们的shell等价命令的核心行为。如果想在本地文件系统中执行这些操作,可以通过使用以下命令进入shell:

sftp> !

或者通过在命令前加上 ! 前缀,来在本地文件系统中运行单个指令:

stfp> !chmod 644 somefile

SFTP会话完毕后,可用 exitbye 关闭连接。

sftp> bye

结语

虽然SFTP语法远不如现代shell工具全面,但它能与传统FTP语法兼容,且当一些环境需要限制远程用户可用功能时会很有用。例如,在没有SSH访问权限的情况下,特定用户可以通过SFTP传输文件。

如果您习惯使用FTP或是SCP传输文件,SFTP是一个兼具二者优点的好方法。虽然并不适用于所有情况,但SFTP是一种很灵活的工具,值得贮备在您的工具箱中。