最近搭建了一个ftp服务器,分享一下踩过的坑。
首先说明,我要搭建的是一个匿名的ftp服务器,对内网所有用户开放,可以任意上传和下载。首先关闭selinux
配置 /etc/selinux Enforcing 变disable。
yum install vsftpd -y
vim /etc/vsftpd/vsftpd.conf
修改:
并且在最后加入:local_root=/var/ftp
chmod 777 /var/ftp/pub
这样,一个简单的匿名ftp服务器就搭好了,连接后会自动进入/var/ftp ,但是只能往pub下传文件。
如果你想修改默认的21端口:
vim /etc/vsftpd/vsftpd.conf
加入如下:
listen_port=8021
vim /etc/services
找到ftp选项并将21修改成你设置的端口,本文为8021
ftp 8021/tcp
ftp 8021/udp fsp fspd
service vsftpd restart
查看端口号是否成功
netstat -utlpn | grep vsftp
附送连接代码:
import sun.net.ftp.FtpClient;
import sun.net.ftp.FtpProtocolException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import com.xxx.collector.client.ftp.FtpUtils;
public class FtpTest {
static String ip = "xx.xx.xxx.xx";
static int port = 9998;//可以修改端口,默认21,我这里修改了
static String username = "ftp";//默认用ftp用户登录
static String password = "ftp";
static String path = "/pub";
public static void main(String[] args) throws FtpProtocolException, IOException {
System.out.println(hostAddress()); // read host ip
upload("F:\\work\\aaa.txt", "afsfsssaf.txt");
// download("F:/Temp/user1@20150925135953.rar",
// "/tmp/users/user1@20150925135953.rar");
}
public static void upload(String localPath, String ftpPath) throws FtpProtocolException, IOException {
// 连接ftp
FtpClient ftp = FtpUtils.connectFTP(ip, port, username, password);
// 切换目录 默认连进去是/var/ftp 我们需要切换到pub,因为只有pub才授予了权限
FtpUtils.changeDirectory(ftp, path);
FtpUtils.upload(localPath, ftpPath, ftp);
FtpUtils.disconnectFTP(ftp);
}
public static void upload(String ip, int port, String username, String password, String Localpath,
String remotePath){
FtpClient ftp = FtpUtils.connectFTP(ip, port, username, password);
FtpUtils.changeDirectory(ftp, remotePath);
FtpUtils.upload(Localpath, remotePath, ftp);
FtpUtils.disconnectFTP(ftp);
}
public static void download(String localPath, String ftpPath){
FtpClient ftp = FtpUtils.connectFTP(ip, port, username, password);
FtpUtils.changeDirectory(ftp, path);
FtpUtils.download(localPath, ftpPath, ftp);
FtpUtils.disconnectFTP(ftp);
}
public static void listFiles(String path) throws FtpProtocolException, IOException {
FtpClient ftp = FtpUtils.connectFTP(ip, port, username, password);
System.out.println(ftp.listFiles(path));
}
public static String hostAddress() throws UnknownHostException {
String address = "";
InetAddress addr = InetAddress.getLocalHost();
address = addr.getHostAddress();
return address;
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import sun.net.ftp.FtpClient;
import sun.net.ftp.FtpProtocolException;
public class FtpUtils {
/**
* 连接ftp服务器
*
* @param url
* @param port
* @param username
* @param password
*
* @return FtpClient
* @throws FtpProtocolException
* @throws IOException
*/
public static FtpClient connectFTP(String url, int port, String username, String password){
// 创建ftp
FtpClient ftp = null;
// 创建地址
SocketAddress addr = new InetSocketAddress(url, port);
// 连接
ftp = FtpClient.create();
try {
// 登陆
ftp.connect(addr);
ftp.login(username, password.toCharArray());
ftp.setBinaryType();
} catch (Exception e) {
throw new RuntimeException("ftp连接登录出现错误!", e);
}
return ftp;
}
/**
* 切换目录
*
* @param ftp
* @param path
* @throws IOException
* @throws FtpProtocolException
*/
public static void changeDirectory(FtpClient ftp, String path){
try {
ftp.changeDirectory(path);
} catch (Exception e) {
throw new RuntimeException("转换目录出现错误!", e);
}
}
/**
* 关闭ftp
*
* @param ftp
* @throws IOException
*/
public static void disconnectFTP(FtpClient ftp){
try {
ftp.close();
} catch (IOException e) {
throw new RuntimeException("关闭ftp连接出现错误!", e);
}
}
/**
* 上传文件
*
* @param localFile
* @param ftpFile
* @param ftp
* @throws IOException
* @throws FtpProtocolException
*/
public static void upload(String localFile, String ftpFile, FtpClient ftp){
OutputStream os = null;
FileInputStream fis = null;
// 将ftp文件加入输出流中。输出到ftp上
try {
os = ftp.putFileStream(ftpFile);
File file = new File(localFile);
// 创建一个缓冲区
fis = new FileInputStream(file);
byte[] bytes = new byte[1024];
int c;
while ((c = fis.read(bytes)) != -1) {
os.write(bytes, 0, c);
}
System.out.println("upload success!!");
} catch (Exception e) {
throw new RuntimeException("上传文件出错!", e);
} finally {
try {
if (os!=null) {
os.close();
}
if (fis != null) {
fis.close();
}
} catch (IOException e) {
throw new RuntimeException("上传文件关流出错!", e);
}
}
}
/**
* 文件下载
*
* @param localFile
* @param ftpFile
* @param ftp
* @throws IOException
* @throws FtpProtocolException
*/
public static void download(String localFile, String ftpFile, FtpClient ftp) {
InputStream is = null;
FileOutputStream fos = null;
try {
// 获取ftp上的文件
is = ftp.getFileStream(ftpFile);
File file = new File(localFile);
byte[] bytes = new byte[1024];
int i;
fos = new FileOutputStream(file);
while ((i = is.read(bytes)) != -1) {
fos.write(bytes, 0, i);
}
System.out.println("download success!!");
} catch (Exception e) {
throw new RuntimeException("下载文件出错!", e);
} finally {
try {
fos.close();
is.close();
} catch (IOException e) {
throw new RuntimeException("下载文件关流出错!", e);
}
}
}
}
常见问题:
553 Could not create file
这个问题的常见原因是上传目录没有写入权限,只要配置想要上传的目录为777权限即可 如: chmod 777 /var/ftp/pub
vsftpd:500 OOPS: vsftpd: refusing to run with writable root inside chroot ()
这个问题原因很多,我的原因是把/var/ftp这个目录设权限为777了,ftp禁止设置这个目录为777,我们可以吧这个目录设置为755,然后mkdir一个子目录比如/upload 然后把这个子目录设置为777,通过上面代码里面的changeDirectory方法改为/upload
当然也可以设置
vi /etc/vsftpd/vsftpd.conf
添加 allow_writeable_chroot=YES
,这个方法我感觉能行,未测试,上面的解决方法经过测试,能够解决问题
还有一个问题是,配置都正常,但就是连不上ftp。这种情况有可能是防火墙未关闭,但是端口未开,ftp工具有两种连接方式,主动和被动,这两种方式都需要打开两个端口,主要要求21端口和20端口(反正就是自己配置的端口和这个端口号-1的端口),而被动模式则需要打开21端口和任意一端口(貌似是5000以内?具体没仔细看),如果你怎么都连不上,尝试注意一下防火墙和端口是否打开。
详细讲解:http://blog.csdn.net/houbin0912/article/details/72578688
http://blog.sina.com.cn/s/blog_7b6fc4c901014eyv.html
首先看看是否打开ftp服务器以及端口,然后看看你登录的用户是否存在于一下两个文件:vsftpd.ftpusers,vsftpd.user_list
vsftpd.ftpusers:位于/etc/vsftpd目录下。它指定了哪些用户账户不能访问FTP服务器,例如root等。
vsftpd.user_list:位于/etc/vsftpd目录下。该文件里的用户账户在默认情况下也不能访问FTP服务器,仅当vsftpd .conf配置文件里启用userlist_enable=NO选项时才允许访问。
vsftpd.conf:位于/etc/vsftpd目录下。来自定义用户登录控制、用户权限控制、超时设置、服务器功能选项、服务器性能选项、服务器响应消息等FTP服务器的配置。
检查完毕后重启service vsftpd restart