SFTP(SSH File Transfer Protocol,SSH 文件传输协议)是一种安全、可靠的文件传输协议。它通过 SSH(Secure Shell)通道运行,所有数据(包括用户名、密码和传输的文件内容)都经过加密,因此非常安全。SFTP 功能强大,类似于 FTP,但安全性远超 FTP。
SFTP和FTP的主要区别如下表:
| 特性 | SFTP (SSH File Transfer Protocol) | FTP (File Transfer Protocol) |
|---|---|---|
| 协议 | 基于 SSH | 独立的 TCP 协议 |
| 端口 | 默认通过 SSH 的 22 端口 | 默认使用 20 和 21 端口 |
| 安全性 | 高,所有数据均加密 | 低,数据以明文传输 |
| 连接方式 | 单个连接传输控制命令和数据 | 需要两个连接:一个控制连接,一个数据连接 |
| 功能 | 功能更丰富,支持文件和目录的更多操作 | 功能相对单一,主要用于文件上传/下载 |
连接SFTP服务器
首先,你需要安装SFTP客户端。在Linux和macOS系统中,通常已经内置了sftp命令行工具。
在终端中,使用以下命令连接到远程服务器:
bash
sftp <username>@<hostname_or_ip>
# <username>: 你的远程服务器用户名。
# <hostname_or_ip>: 远程服务器的域名或 IP 地址。
# 示例如下:
sftp myuser@192.168.1.100
# 成功连接后,你会看到欢迎信息,并进入SFTP提示符:
sftp>
SFTP命令分类
SFTP命令可以分为以下几类:连接帮助、文件传输、本地操作、远程操作、目录操作、文件属性和信息。
1. 连接与帮助命令
显示所有可用命令的帮助信息的命令如下:
bash
help 或 ?
退出SFTP会话,临时返回到本地终端可以在命令添加添加一个感叹号。命令如下:
bash
# 示例
!ls -l /tmp
# 在本地命令执行后,使用exit返回SFTP会话。
终止SFTP会话并退出SFTP环境的命令如下:
bash
bye
# 或者
exit
2. 文件传输命令
命令语法如下:
bash
<put/get> [-r] <local_file/path> <remote_file/path>
# 注意
-r (recursive): 递归操作,用于上传或下载整个目录。
文件传输命令是SFTP最核心的功能命令,用于在本地和远程之间传输文件。
bash
# 上传文件/目录从本地到远程服务器。
put local_file.txt /remote_dir/remote_file.txt
put -r local_dir /remote_dir/
# 下载文件/目录从远程服务器到本地。
get remote_file.txt /home/user/local_file.txt
get -r remote_dir /home/user/local_dir/
注意:
- 如果目标路径(本地或远程)是一个目录,文件将被下载或上传到该目录下,并保持原名。
- 如果目标路径已存在同名文件,它将被覆盖,且不会有任何提示。请谨慎操作。
3. 本次操作命令
这些命令用于操作你当前计算机(客户端)上的文件系统。这些命令前都带有一个 l (local) 前缀。
bash
# 切换本地的当前工作目录。
lcd /home/user/documents
# 列出本地当前目录下的文件和目录。
lls -l (等同于 ls -l)
# 在本地创建一个新的目录。
lmkdir new_local_folder
# 显示本地的当前工作目录路径。
lpwd
# 在本地重命名一个文件或目录。
lrename old_name.txt new_name.txt
4. 远程操作指令
这些命令用于操作你已连接的远程服务器上的文件系统。它们是 SFTP 的核心操作命令。
bash
# 切换远程服务器的当前工作目录。
cd /var/www/html
# 列出远程当前目录下的文件和目录。
ls -l (显示详细信息)<br>ls -a (显示包括隐藏文件)
# 在远程服务器上创建一个新的目录。
mkdir new_remote_folder
# 显示远程服务器的当前工作目录路径。
pwd
# 在远程服务器上重命名一个文件或目录。
rename old_name.txt new_name.txt
5. 脚本自动化
sftp命令也可以被写入脚本中,与-b选项结合使用,可以实现无人值守的文件自动传输。
bash
# 示例:自动化脚本
# sftp -b batch_script.txt deploy@192.168.1.100
# batch_script.txt 内容:
# cd /var/www/html
# put /path/to/local_file.txt /remote/path/to/file.txt
# bye
sftp命令的核心自动化参数是-b或--batch。
bash
sftp [options] -b <batch_script_file> <username>@<hostname>
- -b <batch_script_file>: 指定一个包含SFTP命令的文本文件。SFTP会读取这个文件并按行执行命令。
- <batch_script_file>: 这就是我们的"指令剧本",纯文本文件,每行写一个SFTP命令(例如 put, get, cd, mkdir 等)。
- <username>@<hostname>: 远程服务器的登录信息。
注意:批处理的sftp脚本文件中只能编写sftp的标准命令,不能书写shell命令。常用的命令列表如下:
| SFTP 命令 | 作用 | 示例 |
|---|---|---|
cd <remote_path> |
切换远程目录 | cd /data/remote_dir |
lcd <local_path> |
切换本地目录 | lcd /data/local_dir |
put <local_file> [remote_file] |
上传文件/目录 | put file.txt remote_file.txt<br>put -r local_dir remote_dir/ |
get <remote_file> [local_file] |
下载文件/目录 | get file.txt local_file.txt<br>get -r remote_dir local_dir/ |
ls [remote_path] |
列出远程内容 | ls -l /data |
lls [local_path] |
列出本地内容 | lls |
mkdir <remote_path> |
在远程创建目录 | mkdir new_folder |
rename <old_name> <new_name> |
远程重命名 | rename old.log new.log |
rm <remote_file> |
远程删除文件 | rm unwanted_file.tmp |
rmdir <remote_dir> |
远程删除空目录 | rm empty_dir |
bye 或 exit |
结束 SFTP 会话 | bye |
场景: 每日凌晨,将本地服务器上 /data/backup/ 目录下的所有文件,通过 SFTP 自动上传到远程服务器的 /home/user/backups/ 目录下。
第一步:准备"指令剧本"
创建一个名为 upload.sftp 的文件,内容如下:
bash
# 文件名: upload.sftp
# 描述: SFTP 自动上传指令剧本
# 切换到远程目标目录
cd /home/user/backups
# 设置上传文件权限 (可选,但推荐)
chmod 644 *
# 退出 SFTP 会话,非常重要!
bye
第二-步:编写 Shell 脚本
创建一个名为 auto_upload.sh 的 Shell 脚本来调用 upload.sftp。
bash
#!/bin/bash
# 脚本名称: auto_upload.sh
# 描述: 通过非交互式 SFTP 自动上传文件到远程服务器。
# --- 1. 定义变量 ---
SFTP_SCRIPT="upload.sftp" # SFTP 指令剧本文件名
REMOTE_USER="sftp_user" # 远程服务器 SFTP 用户名
REMOTE_HOST="remote.server.com" # 远程服务器地址
REMOTE_DIR="/home/user/backups" # 远程目标目录
LOCAL_DIR="/data/backup" # 本地源目录
LOG_FILE="/var/log/sftp_upload.log"
# --- 2. 检查本地源目录是否存在 ---
if [ ! -d "${LOCAL_DIR}" ]; then
echo "[错误] 本地源目录 ${LOCAL_DIR} 不存在,脚本退出。" >> ${LOG_FILE}
exit 1
fi
# --- 3. 检查 SFTP 指令剧本是否存在 ---
if [ ! -f "${SFTP_SCRIPT}" ]; then
echo "[错误] SFTP 指令剧本 ${SFTP_SCRIPT} 不存在,脚本退出。" >> ${LOG_FILE}
exit 1
fi
# --- 4. 显示开始信息并记录日志 ---
echo "#############################################################" >> ${LOG_FILE}
echo " $(date '+%Y-%m-%d %H:%M:%S') - 开始 SFTP 自动化上传任务" >> ${LOG_FILE}
echo "#############################################################" >> ${LOG_FILE}
# --- 5. 执行 SFTP 命令 (核心步骤) ---
# 使用 rsync 可以更好地处理错误,但 sftp -b 更直接
sftp -b ${SFTP_SCRIPT} ${REMOTE_USER}@${REMOTE_HOST}
if [ $? -eq 0 ]; then
echo "[成功] SFTP 上传任务成功完成。" >> ${LOG_FILE}
else
echo "[失败] SFTP 上传任务执行失败,请检查日志和服务器连接。" >> ${LOG_FILE}
# 这里可以增加告警逻辑,如发送邮件
fi
echo "任务结束。" >> ${LOG_FILE}
echo "" >> ${LOG_FILE}
exit 0
第三步:使用与测试
bash
# 赋予执行权限
chmod +x auto_upload.sh
chmod 644 upload.sftp
# 手动执行并调试
./auto_upload.sh
如果脚本失败,最常见的原因是密码输入。如前所述,将密码硬编码在脚本中是极其危险的。最佳实践是在远程服务器上创建一个专门的、无交互登录权限的 SFTP 用户,并通过SSH密钥对进行认证。这样就可以在脚本中实现无密码登录。
6.无密码登录
为了让脚本真正"无人值守",必须避免手动输入密码。这需要设置公钥认证。
bash
# 在本地服务器上生成 SSH 密钥对 (如果还没有):
ssh-keygen -t rsa -b 4096
此过程会生成 ~/.ssh/id_rsa (私钥) 和 ~/.ssh/id_rsa.pub (公钥)。私钥必须保密,公钥可以分发。
以下命令会将你的公钥内容追加到远程服务器上 sftp_user 用户的 ~/.ssh/authorized_keys 文件中。
bash
# 将公钥上传到远程服务器
ssh-copy-id -i ~/.ssh/id_rsa.pub \
${REMOTE_USER}@${REMOTE_HOST}
输入一次 sftp_user 用户的密码即可。之后,你就可以从本地服务器无密码地 SSH 登录到远程服务器了。
验证与测试
bash
ssh ${REMOTE_USER}@${REMOTE_HOST}
如果能直接登录,无需密码,说明密钥对配置成功。此时你的 Shell 脚本中的 sftp -b ... 命令也将能自动执行,不会再索要密码。