Ошибка sshtools.SftpClient.put с "Нет такого файла"

Я унаследовал проект на основе Java, который включает в себя задание cron для загрузки файла через SFTP на сторонний сервер. Вот соответствующий код.

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".

Я что-то упустил? Есть другие идеи?

-Sean

1 ответ

Решение

От callstack и вашего описания, я ожидаю, что ошибка относится к удаленному файлу.

chmod должно быть сделано только после завершения передачи, поэтому я предполагаю, что SftpClient считает, что передача выполнена, и пытается обновить права доступа к удаленному файлу. И кажется, что это терпит неудачу, потому что файл на самом деле не там. Как только вы получите ошибку, используйте SftpClient.ls(), чтобы проверить, если файл там. Скорее всего, у вас есть какой-то удаленный процесс, который забирает файл в момент завершения загрузки.

В качестве обходного пути вы также можете попытаться предотвратить SftpClient пытаясь изменить разрешения после завершения загрузки. Я не знаю J2SSH. Беглый взгляд, я не нашел API для этого, хотя. Может быть SftpClient.umask(),

Вы можете попробовать переключиться на JSch. Это не похоже на неявное chmod после загрузки.

Также стоит проверить журнал удаленного сервера.

Другие вопросы по тегам