![Python自动化运维快速入门](https://wfqqreader-1252317822.image.myqcloud.com/cover/815/26846815/b_26846815.jpg)
2.6 搭建FTP服务器与客户端
熟悉FTP的读者可能会觉得这个太简单了,直接在网上下载软件安装运行就可以了,客户端和服务器都有,但是只能满足一些简单的工作需求。如果我们通过写Python代码搭建FTP服务器和客户端,就能实现一些更为精细化的控制,如精细的访问权限配置、详细的日志记录等,根据工作经验,Python搭建FTP服务器也非常简单,而且更为稳定,下面就让我们一起来学习吧。
2.6.1 搭建FTP服务器
FTP(File Transfer Protocol,文件传输协议)运行在TCP协议上,使用两个端口,即数据端口和命令端口,也称控制端口。默认情况下,20是数据端口,21是命令端口。
FTP有两种传输模式:主动模式和被动模式。
(1)主动模式:客户端首先从任意的非特殊端口n(大于1023的端口,也是客户端的命令端口)连接FTP服务器的命令端口(默认是21),向服务发出命令PORT n+1,告诉服务器自己使用n+1端口作为数据端口进行数据传输,然后在n+1端口监听。服务器收到PORT n+1后向客户端返回一个’ACK’,然后服务器从它自己的数据端口(20)到客户端先前指定的数据端口(n+1端口)的连接,最后客户端向服务器返回一个'ACK',过程结束,如图2.17所示。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P106_47834.jpg?sign=1738885556-o3WEHl9ocjoLFUeqhMIh84muZo9IP5vQ-0-df7159a213d75b2e2222c17222b75846)
图2.17 ftp的主动模式
(2)被动模式:为了解决服务器发起到客户的连接问题,人们开发了被动FTP,或者叫作PASV,当客户端通知服务器处于被动模式时才启用。在被动方式FTP中,命令连接和数据连接都由客户端发起。当开启一个FTP连接时,客户端打开两个任意的非特权本地端口(大于1023)。第一个端口连接服务器的21端口,但与主动方式的FTP不同,客户端不会提交PORT命令并允许服务器来回连接数据端口,而是提交PASV命令。这样做的结果是服务器会开启一个任意的非特权端口,并发送PORT P命令给客户端,然后客户端发起从本地端口N+1到服务器的端口P的连接用来传送数据,如图2.18所示。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P107_47835.jpg?sign=1738885556-u4nthLKzbKLoyLOGeNL1L1PgR08oG2Vv-0-7d0e3127f686a96bf17e620f8bdb34b2)
图2.18 ftp的被动模式
简单总结:主动方式对FTP服务器的管理有利,但对客户端的管理不利。因为FTP服务器企图与客户端的高位随机端口建立连接,而这个端口很有可能被客户端的防火墙阻塞掉。被动方式对FTP客户端的管理有利,但对服务器端的管理不利。因为客户端要与服务器端建立两个连接,其中一个连到一个高位随机端口,而这个端口很有可能被服务器端的防火墙阻塞掉。
使用Python搭建一个FTP服务器需要pyftpdlib模块,安装非常简单。执行以下命令进行安装:
pip install pyftpdlib
(1)快速搭建一个简单的FTP服务器。执行:
python -m pyftpdlib -p 21
即可在执行命令所在的目录下建立一个端口为21的供下载文件的FTP服务器,注意Linux系统需要root用户才能使用默认端口21,windows系统中目录文件名可能是乱码,原因是pyftpdlib内部使用utf8,而windows使用gbk,参照下面的步骤可解决windows系统的乱码问题。
首先,找到pyftpdlib源文件所在的目录。
>>> import pyftpdlib >>> pyftpdlib.__path__ ['C:\\Users\\xx\\projectA_env\\lib\\site-packages\\pyftpdlib']
其次,在目录pyftpdlib源文件所在的目录找到文件filesystems.py和handlers.py,先备份。
再次,打开filesystems.py,找到
yield line.encode('utf8', self.cmd_channel.unicode_errors)
共有两处,修改'utf8'为'gbk',保存并退出。
打开handlers.py,找到
return bytes.decode('utf8', self.unicode_errors)
修改utf8为gbk,保存并退出。
最后,验证乱码已解决。
(2)搭建一个具有访问权限,可配置相关信息的FTP服务器(ftpserver.py)。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P108_46835.jpg?sign=1738885556-GdGBnX6oEmgDcE9G3i7FaKOW52upm1Nf-0-27fc4b6ec8f8ebaacf85114e396e92a3)
执行python ftpserver.py得到如图2.19所示的结果。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P109_18104.jpg?sign=1738885556-pQJ9qtkDGCPbLg3lphjohxO2ZXhH6Efr-0-a6831ae9f22cf64d49a7ac788b73a227)
图2.19 运行结果
同时该目录下也会生成一个myftpserver.log文件,文件内容与屏幕上的信息一致。
下面我们登录该FTP并列出目录进行测试,如图2.20所示。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P109_18108.jpg?sign=1738885556-4dOOuKwfZLPozCYeF6xVIwDCfyeDhd0O-0-15fdd73192dcfae501e0b5e776d2b606)
图2.20 客户端运行结果
对应服务器的打印信息如图2.21所示。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P110_18122.jpg?sign=1738885556-Gg0ahEx22obyI73kK5EdK07X3q4Wxvi5-0-05fed2264f8c1ea9c669ab16c8cebe91)
图2.21 服务端运行结果
至此,一个FTP服务器已经搭建完成,大家可以修改ftpserver.py来满足自己的需求。
在此附上用户权限的代码及说明,参见表2-7和表2-8。
表2-7 读权限
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-T110_46837.jpg?sign=1738885556-R5em5e6o3VJdDtdpFDAoqcoYHzfK08Rv-0-7752cc03f0bb62d8b6a73c801a724747)
表2-8 写权限
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-T110_46838.jpg?sign=1738885556-LILNFMqjNe44piSpm4WIMfF3Iv9vXHP8-0-3ce3202c6020ec07310354134b4dcd2b)
2.6.2 编写FTP客户端程序
在实际应用中可能经常访问FTP服务器来上传或下载文件,Python也可以替我们做这些。
【示例2-28】下面请看一个例子(ftpclient)。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P110_46839.jpg?sign=1738885556-8vM54gnm1CRJOvhI4o9nT3TsiKnTk9Op-0-cf2d7afb1f1a6a1ea270794e2f2cea78)
运行结果如图2.22所示。
![](https://epubservercos.yuewen.com/C3ED30/15289822304506406/epubprivate/OEBPS/Images/Figure-P111_18447.jpg?sign=1738885556-pOPU9Z1dza9TmOKm16HUrg0tFg447cUC-0-86baf17ba22fa0aa241bb553346586c5)
图2.22 运行结果
FTP客户端程序的编写还可以参照官方文档,以满足个性化的需求。