# 1.简介

FTP(File Transfer Protocol)是一种用于在计算机之间传输文件的标准网络协议。

ftp 则是 FTP 服务的命令行客户端,用于与 FTP 服务器进行交互。

# 2.格式

ftp [OPTIONS] [HOST [PORT]]

控制通道端口 PORT 缺省为 21。

# 3.选项

-4: use IPv4 addresses only
-6: use IPv6, nothing else
-p: enable passive mode (default for pftp)
-i: turn off prompting during mget
-n: inhibit auto-login
-e: disable readline support, if present
-g: disable filename globbing
-v: verbose option forces ftp to show all responses from the remote server, as well as report on data transfer statistics.
-t: enable packet tracing [nonfunctional]
-d: enable debugging
-h: show a brief help message

# 4.子命令

有许多子命令,这些命令用于执行各种操作,例如连接到服务器、文件传输、目录操作等。以下是一些常用的子命令:

?, help [CMD]
	显示所有子命令。如果指定子命令则显示子命令的说明。
open HOST [POST]
	与 FTP 服务器建立连接。
user USERNAME [PASSWD]
	用户登录。需要口令时,必须输入口令。
passive
	进入被动方式。
ascii
	将文件传输模式设置为 ASCII 模式。
binary
	将文件传输模式设置为二进制模式。
pwd
	 显示当前远程工作目录。
cd DIRECTORY
	切换当前远程目录。
ls [DIRECTORY]
	列出(当前)远程目录内容。
dir [DIRECTORY]
	类似于 ls,用于列出(当前)远程目录内容。
get REMOTE_FILE [LOCAL_FILE]
	从服务器下载文件。本地文件路径可省略,缺省下载到当前本地目录。
mget REMOTE_FILES
	批量下载多个文件,支持使用通配符 ? 和 *。
put LOCAL_FILE [REMOTE_FILE]
	上传文件到服务器。
mput LOCAL_FILES
	批量上传多个文件到服务器。
delete REMOTE_FILE
	删除远程文件。
mdelete REMOTE_FILES
	批量删除远程文件。
mkdir DIRECTORY
	创建远程目录。
rmdir DIRECTORY
	删除远程目录。
prompt on | off
	打开(on)或关闭(off)批量命令的交互式询问
!, bye, exit, quit
	关闭连接,退出会话。

这只是一部分子命令,还有其他许多子命令,具体取决于 FTP 服务器的支持和配置。你可以输入 ? 或 help 子命令获取更多子命令的帮助信息。

# 5.控制与数据通道

FTP(File Transfer Protocol)使用两个通道来完成文件传输和命令控制:控制通道(Control Channel)和数据通道(Data Channel)。

控制通道(Control Channel)用于客户端和服务器之间传递控制命令和状态信息,例如登录认证、切换目录等

控制通道通常使用默认端口 21。

数据通道(Data Channel)用于数据传输,传输类型可以是 ASCII 模式(文本文件)或 Binary 模式(二进制文件)。

数据通道的端口通常是服务端事先配置的 20(主动模式)或动态分配(被动模式)。

# 6.主动与被动模式

FTP 使用主动模式(Active Mode)和被动模式(Passive Mode)来建立数据连接,这涉及到在客户端和服务器之间传输文件时的数据通信。

主动与被动是站在 FTP 服务器的角度来说的。

# 主动模式(Active Mode)

客户端请求:FTP 客户端随机开启一个非保留端口(大于 1023)N 向服务器的 21 号命令端口发起连接,发送 FTP 用户名和密码,然后开放 N+1 号端口进行监听,并向服务器发出 PORT N+1 命令,告诉服务器客户端采用主动模式并开放了 N+1 端口。

服务器主动连接: 服务器接收到 PORT 命令后,会用其本地的 FTP 数据端口(通常是20)来连接客户端指定的 N+1 端口,进行数据传输。

主动模式的问题:

主动模式可能会面临防火墙问题,因为在传输文件之前,服务器需要与客户端的数据端口建立连接。如果客户端位于防火墙后面,防火墙可能会阻止来自服务器的连接。

# 被动模式(Passive Mode)

客户端请求: 在被动模式下,客户端随机开启非保留端口(大于 1023)N 向服务器的21号端口发起连接,发送用户名和密码进行登录。同时会开启 N+1 端口用于数据连接,然后向服务器发送 PASV 命令,通知服务器处于被动模式。

服务器响应: 服务器收到命令后,会开放一个非保留端口(大于 1023)P(端口P的范围是可以设置)进行监听,然后用 PORT P 命令通知客户端自己的数据端口是 P。

客户端连接: 客客户端收到命令后,会通过N+1号端口连接服务器的端口P,然后在两个端口之间进行数据传输。

被动模式的优势:

被动模式通常更容易穿越防火墙,因为在被动模式下,客户端与服务器的数据连接是由客户端发起的,而不需要服务器主动连接客户端。

# 7.示例

(1)查看帮助信息。

ftp -h
Usage: { ftp | pftp } [-46pinegvtd] [hostname]
   -4: use IPv4 addresses only
   -6: use IPv6, nothing else
   -p: enable passive mode (default for pftp)
   -i: turn off prompting during mget
   -n: inhibit auto-login
   -e: disable readline support, if present
   -g: disable filename globbing
   -v: verbose mode
   -t: enable packet tracing [nonfunctional]
   -d: enable debugging

(2)在 Shell 脚本中拉取文件到本地。

ftp -np $ftpHost <<END
user DEV DEV
binary
get $remoteFilePath $localFilePath
bye
END

-n 表示禁止自动登录,后由 user 命令登录。-p 表示被动模式,由客户端向服务器发起数据通道的连接。

<<EOF 是 Shell 的 Here Document,作用将后续内容重定向到左侧命令的 Stdin 中,并以指定的任意字符串(示例中使用 END)表示结束。

(3)使用 mget 下载多个文件到本地。

mget 用于批量下载多个文件,支持使用通配符指定文件。

# 下载多个文件
ftp> mget file1.txt file2.txt file3.txt

# 使用通配符下载多个文件
ftp> mget *.txt

默认情况下,mget 会在下载文件时询问用户是否确认下载。你可以使用 prompt 命令关闭询问。

ftp> prompt off

递归下载目录中的文件。

ftp> mget -r remote_directory/*

# 8.FAQ

# ls 报错

使用 ftp HOSTNAME,然后输入用户名密码成功登录之后,使用 ls 报了如下错误:

501 Server cannot accept argument.
ftp: bind: Address already in use

原因是我们处于主动模式。

主动模式下,FTP 服务器使用端口 20 去连接客户端指定的端口建立数据传输通道。一般来讲外部系统到内部的端口连接会被防火墙阻塞,所以报了 ftp: bind: Address already in use 错误。

解决办法是执行 passive 命令进入被动模式。

# 控制连接被断开

使用客户端与服务器建立连接后,过一段时间再次执行命令,会报如下错误:

421 Service not available, remote server has closed connection

描述表示 FTP 服务器已关闭连接,导致无法提供服务。可以使用 open 重新与服务器建立连接。

出现这种情况的原因可能有如下几点:

  • 空闲连接被断开: 一些FTP服务器为了节省资源,会在连接空闲一段时间后主动关闭。尝试在服务器上调整空闲连接断开的设置。
  • 服务器状态异常: 可能是FTP服务器本身出现了问题,例如负载过高或正在维护。联系FTP服务器管理员以获取更多信息。
  • 防火墙设置不当: 检查本地防火墙和服务器防火墙的设置,确保它们不会关闭FTP连接。有时,防火墙可能会关闭长时间没有活动的连接。
  • 网络不稳定:不稳定的网络连接可能导致连接超时和错误。确保你的网络连接是稳定的。

# 下载大文件后阻塞

下载大文件(我下载的文件 >4GB)时发现客户端假死,实际上文件已下载成功,但是没接收到 226 返回码(关闭数据连接,请求的文件操作成功),不继续执行。

下载小文件没有问题。

在这里插入图片描述

下载大文件无法正常结束。

在这里插入图片描述 原因是长时间的数据传输,导致控制连接无任何操作,空闲超时被断开。所以客户端无法接收服务端 226 返回码,出现阻塞。

由于命令行客户端 ftp 不能设置控制连接空闲超时时间,也没有发送心跳用于连接保活的功能,所以暂时无法解决这个问题。

最终改用 wget 下载大文件。

wget ftp://username:password@ftp.example.com/path/to/file

# 参考文献

ftp(1): Internet file transfer program - Linux man page (opens new window)

Ftp下载文件超时处理 - CSDN (opens new window)

FTP下载大文件后命令无法正常退出 - CSDN (opens new window)

ftp get a large file can't end properly - Stack Overflow (opens new window)

Last Updated: 5/17/2024, 1:47:36 AM