最近搭建了一个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/[email protected]", // "/tmp/users/[email protected]"); } 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