0

我继承了一个基于 Java 的项目,其中包括一个通过 SFTP 将文件上传到第三方服务器的 cron 作业。这是相关的代码。

String filePath = IUtil.getInstance().getProperties("cheetah_sftp_filepath");
try{
    SshClient ssh = new SshClient();
    ssh.connect(host, port);
    //Authenticate
    PasswordAuthenticationClient passwordAuthenticationClient = new PasswordAuthenticationClient();
    passwordAuthenticationClient.setUsername(userName);
    passwordAuthenticationClient.setPassword(password);
    int result = ssh.authenticate(passwordAuthenticationClient);
    if(result != AuthenticationProtocolState.COMPLETE){
         throw new Exception("Login to " + host + ":" + port + " " + userName + "/" + password + " failed");
    }
    //Open the SFTP channel
    SftpClient client = ssh.openSftpClient();
    client.cd("autoproc");
    client.put(filePath);
    //disconnect
    client.quit();
    ssh.disconnect();
} catch(Exception e) {
    String message = "Failed during sftp: " + e.getMessage();
    addJobMessage(message, JobMessageType.JOB_MESSAGE_TYPE_ERROR);
    e.printStackTrace();
    return false;
}

非常简单,但它不起作用。执行时client.put(),失败并显示“java.io.IOException:没有这样的文件”。这是堆栈跟踪。

java.io.IOException: No such file
    at com.sshtools.j2ssh.sftp.SftpSubsystemClient.getOKRequestStatus(Unknown Source)
    at com.sshtools.j2ssh.sftp.SftpSubsystemClient.setAttributes(Unknown Source)
    at com.sshtools.j2ssh.sftp.SftpSubsystemClient.changePermissions(Unknown Source)
    at com.sshtools.j2ssh.SftpClient.chmod(Unknown Source)
    at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
    at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
    at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
    at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
    at com.dez.store.scripts.SendEmailShellCommand.sftpToCheetah(SendEmailToCheetahShellCommand.java:99)
    at com.dez.store.scripts.SendEmailShellCommand.execute(SendEmailToCheetahShellCommand.java:34)
    at com.fry.ocp.common.ShellCommandExecutor.main(ShellCommandExecutor.java:90)

filePath是文件的绝对路径。是的,我已经检查了明显的:路径正确并且文件存在。文件权限为 664,因此在任何情况下读取都不会失败,但该进程以 root 身份运行以启动。

我已经尝试了我能想到的一切。

  • 我一直检查目录树的读取权限(有点深)。
  • 我已经尝试过lcd()该目录,一旦我到达那里lpwd()。这似乎很好,但 put 仍然失败,所以长路径名似乎不是问题。
  • 我仔细检查以确保最初写入文件的文件流都被正确关闭。我没有看到任何让我认为这可能是问题的地方。
  • 我尝试使用完整路径创建和实例,j2ssh.sftp.SftpFile以查看它是否可以访问该文件并确保“无此类文件”错误与远程主机无关。当我执行时,SftpFile.canRead()我得到一个空指针异常,所以我认为这是一个本地问题。

我已经很多年没有接触过Java了。说我生疏是轻描淡写的。然而,我们最后一个“Java 人”刚刚退出,我是我店里唯一一个接触过 Java的人,所以我是新的“Java 人”。

我错过了一些简单的东西吗?还有其他想法吗?

-肖恩

4

1 回答 1

1

从调用堆栈和您的描述中,我希望错误指的是远程文件。

chmod只有在传输完成后才能完成,所以我假设相信SftpClient传输已经完成并尝试更新远程文件权限。似乎它失败了,因为该文件实际上不存在。一旦出现错误,请使用SftpClient.ls(), 检查文件是否存在。很可能您有一些远程进程会在上传完成时将文件带走。

作为一种解决方法,您还可以尝试防止SftpClient在上传完成后尝试修改权限。我不知道J2SSH。快速浏览一下,虽然我还没有找到任何 API。也许SftpClient.umask().

您可以尝试切换到JSchchmod上传后似乎没有隐含。

还值得检查远程服务器日志。

于 2013-05-29T04:56:52.263 回答