Apache FtpServer 1.2.1 常用 CLI 命令与工具详解
FtpServer 1.2.1 运维手册:ftpd.sh 与 systemd 服务管理、日志定位、curl/lftp 协议级诊断、口令散列与密钥库工具实测
Apache FtpServer 1.2.1 常用 CLI 命令与工具详解
一、启动脚本 ftpd.sh
1.1 帮助信息
/opt/ftpserver/bin/ftpd.sh --help
实测输出:
Usage: java org.apache.ftpserver.main.CommandLine [OPTION] [CONFIGFILE]
Starts FtpServer using the default configuration of the
configuration file if provided.
--default use the default configuration,
also used if no command line argument is given
-?, --help print this message
命令行仅三个用法:--default(无配置文件内建默认值启动)、--help、以及直接给配置文件路径。所有实际参数都在 XML 里,脚本是薄封装。
1.2 前台启动与主类
cd /opt/ftpserver
bin/ftpd.sh res/conf/ftpd-typical.xml
实测输出:
Using XML configuration file res/conf/ftpd-typical.xml...
FtpServer started
脚本内部等价于(FTPD_HOME 由脚本位置自动推断,支持软链接):
/usr/bin/java -classpath "common/classes:common/lib/*" \
org.apache.ftpserver.main.CommandLine res/conf/ftpd-typical.xml
ftpd.sh 不透传 JVM 参数,需要 -Xmx 等参数时直接调用 java(classpath 通配符由 JVM 展开),这也是 systemd 单元的推荐写法。
1.3 Windows 辅助脚本
bin/ 下另有 ftpd.bat(控制台)、ftpd.exe/ftpdw.exe(原生服务包装)、service.bat(注册 Windows 服务)、appendcp.bat(扩展 classpath),Linux 部署用不到。
二、systemd 服务管理
以下命令假设已按《安装指南》第九章配置 ftpserver.service。
systemctl start ftpserver # 启动
systemctl stop ftpserver # 停止(SuccessExitStatus=143 正常退出)
systemctl restart ftpserver # 重启(改任何配置后必须执行)
systemctl status ftpserver # 状态
systemctl enable ftpserver # 开机自启
systemctl disable --now ftpserver # 停止并取消自启
status 实测输出(节选):
● ftpserver.service - Apache FtpServer 1.2.1
Loaded: loaded (/etc/systemd/system/ftpserver.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2026-10-14 13:27:33 UTC; 5s ago
Main PID: 4760 (java)
Memory: 78.5M
确认监听:
ss -tlnp | grep 2121
实测输出:
LISTEN 0 50 *:2121 *:* users:(("java",pid=3606,fd=62))
三、日志与故障定位
3.1 应用日志
日志由 log4j 写入(10 MB × 10 份滚动):
tail -f /opt/ftpserver/res/log/ftpd.log
每行自带账号与来源 IP(MDC),典型交互记录:
[ INFO] 2026-10-14 13:20:01,629 [] [127.0.0.1] SENT: 220 Service ready for new user.
[ INFO] 2026-10-14 13:20:01,631 [admin] [127.0.0.1] SENT: 331 User name okay, need password for admin.
[ INFO] 2026-10-14 13:20:01,632 [admin] [127.0.0.1] RECEIVED: PASS *****
[ WARN] 2026-10-14 13:20:01,632 [admin] [127.0.0.1] User failed to log in
[ INFO] 2026-10-14 13:20:02,133 [admin] [127.0.0.1] SENT: 530 Authentication failed.
口令一律打码为 PASS *****,日志可放心留存。
3.2 systemd 日志
启动横幅与进程级异常看 journald:
journalctl -u ftpserver -n 5 --no-pager
实测输出:
Oct 14 13:27:33 node1.ftp.example systemd[1]: Started Apache FtpServer 1.2.1.
Oct 14 13:27:33 node1.ftp.example java[4760]: Using XML configuration file res/conf/ftpd-typical.xml...
Oct 14 13:27:34 node1.ftp.example java[4760]: FtpServer started
四、客户端诊断命令
4.1 curl 全流程对话框
curl -v 能完整展示 FTP 命令交互,是排障首选:
curl -v --user demo:demo123 ftp://127.0.0.1:2121/ -o /dev/null
实测输出(节选):
< 220 Service ready for new user.
> USER demo
< 331 User name okay, need password for demo.
> PASS demo123
< 230 User logged in, proceed.
> PWD
< 257 "/" is current directory.
> EPSV
< 229 Entering Passive Mode (|||50050|)
> TYPE A
< 200 Command TYPE okay.
> LIST
< 150 File status okay; about to open data connection.
< 226 Closing data connection.
常用变体:
curl --user admin:admin ftp://127.0.0.1:2121/ # 列目录(读)
curl --user admin:admin ftp://127.0.0.1:2121/文件名 # 下载
curl -T 本地文件 --user admin:admin ftp://127.0.0.1:2121/ # 上传
curl -k --ssl-reqd --user admin:admin ftp://127.0.0.1:2121/ # 显式 FTPS
curl --user anonymous: ftp://127.0.0.1:2121/ # 匿名
关键响应码:331 要口令 → 230 成功;530 认证失败(口令格式错/账号禁用);421 并发达到上限;550 无权限或文件不存在;450 无权限执行删除类操作。
4.2 lftp 会话与协议调试
lftp -u admin,admin 127.0.0.1 -p 2121 -e 'set ftp:ssl-allow no; ls; bye'
加 -d 输出协议级调试,含 FEAT 能力协商:
---> FEAT
<--- 530 Access denied.
---> USER demo
<--- 331 User name okay, need password for demo.
---> PASS demo123
<--- 230 User logged in, proceed.
---> FEAT
<--- 211-Extensions supported
<--- SIZE
<--- MDTM
<--- REST STREAM
<--- LANG en;zh-tw;ja;is
<--- MLST Size;Modify;Type;Perm
<--- AUTH SSL
<--- AUTH TLS
<--- MODE Z
<--- UTF8
<--- TVFS
<--- MD5
<--- MMD5
<--- MFMT
<--- 211 End
注意登录前 FEAT 被拒(530 Access denied)是 FtpServer 的正常行为,登录后才返回能力表。lftp 默认尝试 TLS,自签名证书环境要么 set ssl:verify-certificate no,要么如上关闭 ssl-allow。
五、口令与密钥工具
5.1 生成口令散列
printf %s demo123 | sha512sum | awk '{print $1}'
实测输出:
45153ecd716a4b5bb7779d43fb38b3b115e384425ce7d4a75fc410199b19558055dd6d09b8b96847ad658f1c474ed081c252e40a0078dd8b0a41bebefa857721
printf %s(不带换行)很关键,echo 会追加 \n 导致散列值错误。改口令后必须重启进程(用户文件不热加载)。
5.2 keytool 密钥库操作
查看密钥库(口令与证书信息):
keytool -list -v -keystore /opt/ftpserver/res/ftpserver.jks -storepass password | head -12
实测输出(节选):
Alias name: apache ftpserver example
Creation date: Jun 19, 2011
Entry type: PrivateKeyEntry
Signature algorithm name: SHA1withDSA (weak)
Subject Public Key Algorithm: 1024-bit DSA key (weak)
生成新的 RSA 密钥库:
keytool -genkeypair -alias ftpserver -keyalg RSA -keysize 2048 -validity 3650 \
-keystore /opt/ftpserver/res/ftpserver-rsa.jks -storepass password -keypass password \
-dname "CN=node1.ftp.example, O=Demo, C=CN"
实测输出(节选):
ftpserver, Oct 14, 2026, PrivateKeyEntry,
Certificate fingerprint (SHA-256): 03:AF:60:F9:48:02:EA:D7:A6:83:F4:5C:3E:99:0F:D9:2A:27:52:C5:E4:FF:31:95:82:8D:59:57:0A:A4:DA:C2
六、日常运维场景速查
6.1 新增/修改用户并生效
printf %s 新口令 | sha512sum | awk '{print $1}'
vi /opt/ftpserver/res/conf/users.properties # 追加/修改 ftpserver.user.<名>.* 段
systemctl restart ftpserver
curl --user 用户名:口令 ftp://127.0.0.1:2121/ # 验证
6.2 验证限速与并发限制
- 限速:
dd造固定大小文件后time curl -s --user demo:demo123 ftp://127.0.0.1:2121/512kb.bin -o /dev/null,实测 10240 B/s 配置下载 512 KB 耗时 51.2s - 并发:保持一个会话在线再开第二个登录,maxloginnumber=1 时第二个返回
421 Maximum login limit has been reached.
6.3 验证被动端口段
配置 <passive ports="50000-50100" /> 重启后观察 EPSV 响应端口是否落区间:
< 229 Entering Passive Mode (|||50039|)
6.4 TLS 握手排障
curl -v --ssl-reqd --user admin:admin ftp://127.0.0.1:2121/ 2>&1 | grep -E 'AUTH|234|alert|error'
出现 234 Command AUTH okay 说明服务器接受了 AUTH,随后 alert handshake failure 即密钥库证书问题(旧 DSA 证书),换新生成的 RSA 密钥库。
6.5 磁盘与目录健康
ss -tlnp | grep java # 端口在监听
ls -lh /opt/ftpserver/res/log/ # 日志滚动是否正常
df -h /data/ftp # FTP 数据分区容量
七、参考链接
- 配套安装文档:《Ubuntu 22.04 安装 Apache FtpServer 1.2.1 指南》
- 配套配置文档:《Apache FtpServer 1.2.1 配置参数详解》
- 项目主页:https://mina.apache.org/ftpserver-project/