Ошибка 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
после загрузки.
Также стоит проверить журнал удаленного сервера.