记录一次SFTP文件上传异常

目录

一、异常展示

1.1.日志报错 

 1.2.nacos中SFTP参数配置

二、bug溯源 

2.1.本地代码排查

2.1.1.核心代码展示 

2.1.2.补充说明

2.2.本地测试 

 2.3.服务器测试

2.4.SFTP排查 

2.4.1.SFTP访问权限排查 

2.4.2.SFTP展示权限排查

三、SFTP配置文件权限说明       

四、liunx权限说明 


一、异常展示

1.1.日志报错 

 1.2.nacos中SFTP参数配置

         上周客户反应,本地文件生成后,在上传文件时创建SFTP目录时失败,既然有问题,那就找呗,毕竟工作不就是创造bug和解决bug么。由异常报错可知,文件是在上传时,创建SFTP目录时失败,而SFTP的目录是 /1001**********23/,下面记录一下解决问题的思路。

二、bug溯源 

2.1.本地代码排查

2.1.1.核心代码展示 

public void upload1(String directory,String name, String sftpFileName, InputStream input) throws SftpException {
		try {
			//创建一级目录
			sftp.cd(directory);
		} catch (SftpException e) {
			logger.warn("directory is not exist:1级目录"+directory);
			//创建多级目录
			createDir(directory,sftp);
			sftp.cd(directory);
		}
		//创建2级目录
		try {
			sftp.cd(directory+name);
		} catch (Exception e) {
			logger.warn("directory is not exist:2级目录"+directory+name);
			sftp.mkdir(directory+name);
			sftp.cd(directory+name);
		}
		
		sftp.put(input, sftpFileName);
		logger.info("file:{} is upload successful", sftpFileName);
	}

	
	/**
	 * 创建一个文件目录
	 */
	public void createDir(String createpath, ChannelSftp sftp) {
		try {
			if (isDirExist(createpath)) {
				this.sftp.cd(createpath);
				return;
			}
			String pathArry[] = createpath.split("/");
			StringBuffer filePath = new StringBuffer("/");
			for (String path : pathArry) {
				if ("".equals(path)) {
					continue;
				}
				filePath.append(path + "/");
				if (isDirExist(filePath.toString())) {
					sftp.cd(filePath.toString());
				} else {
					// 建立目录
					sftp.mkdir(filePath.toString());
					// 进入并设置为当前目录
					sftp.cd(filePath.toString());
				}
			}
			this.sftp.cd(createpath);
		} catch (SftpException e) {
			logger.error("创建路径错误:"+createpath);
		}
	}

	/**
	 * 判断目录是否存在
	 */
	public boolean isDirExist(String directory) {
		boolean isDirExistFlag = false;
		try {
			SftpATTRS sftpATTRS = sftp.lstat(directory);
			isDirExistFlag = true;
			return sftpATTRS.isDir();
		} catch (Exception e) {
			if ("no such file".equals(e.getMessage().toLowerCase())) {
				isDirExistFlag = false;
			}
		}
		return isDirExistFlag;
	}

         由客户的日志反馈可知,是upload1方法在创建一级目录时失败,上面是创建一级目录的代码。

2.1.2.补充说明

         本地目录创建和SFTP目录创建是不一样的,本地可以一次性创建多级目录,详情请看本地多级目录创建   ,可以直接用mkdirs()方法进行创建多级目录。而SFTP不一样,SFTP没有这个方法,只能用mkdir()方法一级一级创建,具体展示如下:

2.2.本地测试 

        在排查错误时,除了明显的编写错误以外,别的错误都是不好直接看出来的。所以我们在寻找错误的过程中,Debug是最常用的方法,这里没有上传视频,看图片也差不多的。 

        截止到这里,符合图片中的日志打印  

        进一步Debug发现,创建多级目录正常,并无报错。 

        根据本地 Debug 寻找,发现文件目录正常创建,并没有报错。没报错说明代码的设计是没有问题的,那就需要找系统的问题了。系统方面包含两方面,一方面是本地系统异常,包含白名单和登录失败等问题;一方面是客户SFTP服务器异常,包含创建目录权限限制和SFTP系统配置等。

 2.3.服务器测试

        这个是用测试服务器和测试SFTP运行的程序,我通过一次性创建5级目录 /1000066666/ICBCRecon/01/02/03/200028029321208/ ,进一步验证了不是代码的问题,同时,我们联系客户,也确认了是①服务器和SFTP之间是不需要添加白名单的,②登录是可以正常登录,③生产环境在访问SFTP时,SFTP的端口也是经过服务器防火墙放行的,这个流程就不做记录了。 

2.4.SFTP排查 

2.4.1.SFTP访问权限排查 

        由上述排查可知,程序是可以正常创建多级目录的,那么代码bug的几率就很小了。检查SFTP创建目录的权限。

         用nacos 中配置的SFTP用户登录SFTP,并且在 /1001**********23/  目录的上一层创建 test 目录,发现报的是没有权限。

         然后在 /1001**********23/  目录的下一层创建 test 目录,发现是可以创建的。

         由上述操作可知,当用指定用户创建目录时,权限是没问题的。代码没问题,权限没问题,那就要看SFTP配置问题了。

2.4.2.SFTP展示权限排查

        从上图可以看到,当前目录是 /data/sftpsite/szfs/1001001001000023/  ,与nacos配置相比,多出来了 /data/sftpsite/szfs/  ,那么就有可能是SFTP目录权限的问题,具体还需要验证。

        寻找SFTP的ssh配置文件,文件路径 /etc/ssh/sshd_config ,可以看到:

        左边是当前SSH配置文件,文件为初始化配置文件,并没有对目录进行权限限制,右边是应该有的权限配置。

        从系统的历史操作可以看到 ,在2023年11月22日,配置文件被修改过,所以系统原有的配置操作被初始化掉了,造成了突然的创建目录异常。 

        根据配置文件可知,原本添加的权限限制都没了,所以这个时候,nacos 配置的路径就应该是系统全路径,也就是系统绝对路径 ,只配置相对路径是访问不到SFTP目录的,所以才会创建目录失败。

        所以解决bug有两种操作,一是将权限添加上,然后系统还访问相对路径;一是不添加权限,系统访问绝对路径。 

三、SFTP配置文件权限说明       

        在一般情况下,用户登录上SFTP以后,看到的目录结构都是相对路径,也就是说是经过限制的路径,而非从系统的根路径开始展示,那么合理的添加限制有哪些作用呢?

        在SFTP的配置文件/etc/ssh/sshd_config中添加用户访问权限,可以带来以下几个好处:

  1. 安全性增强:通过设置正确的用户访问权限,可以限制哪些用户可以访问特定的目录或文件,从而提高系统的安全性。
  2. 灵活性增加:可以针对不同的用户或用户组设置不同的访问权限,提供更加灵活的文件访问控制。
  3. 资源管理优化:通过合理的权限设置,可以更好地管理和分配系统资源,避免资源的浪费或过度使用。
  4. 审计和监控:对于有权限访问敏感信息的用户,可以实施更严格的审计和监控措施,确保系统的合规性和安全性。

四、liunx权限说明 

        我上面在2.4.1进行访问权限排查时,是直接用工具进行目录创建测试,而在Linux中,实际上是不需要创建,只看文件就行,具体操作如下:

        在Linux系统中,您可以使用ls -l命令来查看文件操作权限。这个命令会以长格式列出文件和目录的信息,包括权限、所有者、所属组和其他属性。

        以下是使用ls -l命令的示例:

ls -l filename

        其中,"filename"是您要查看权限的文件或目录的名称。执行该命令后,将显示类似于以下的结果:

-rw-r--r-- 1 user group 1234 Oct 23 10:00 filename

        您还可以使用 ll 命令来查看文件操作权限,它是ls -l命令的别名。在终端中输入ll命令即可:在这个例子中,文件权限被表示为"-rw-r--r--"。这些字符按照三个一组划分,分别代表所有者、所属组和其他用户的权限。每组的三个字符分别表示读(r)、写(w)和执行(x)权限。如果权限被拒绝,则表示为"-"。

ll filename

        这将以长格式列出文件或目录的详细信息,包括权限、所有者、所属组和其他属性。SFTP查看示例如下:

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值