У меня есть клиентское приложение Java SFTP для регулярного сканирования папки. Как только пара файлов (datafile и datafile.md5) существует, приложение загрузит оба файла на SFTP-сервер.
Приложение работает нормально, за исключением случайного исключения com.jcraft.jsch.SftpException - Нет такое исключение файла или каталога с кодом ошибки 2. Я не могу найти какой-либо общий шаблон с точки зрения времени исключения и файлов исключений. Приложение выйдет после нескольких попыток в logi c. Однако, если я просто перезапущу приложение, загрузка снова будет go плавно до следующего случайного исключения. Это происходит один раз в несколько дней.
Что еще может go не так, и как это исправить? Я понятия не имею, что может быть причиной root. Ниже представлена трассировка стека.
2020-08-06 02:45:17.890 DEBUG 5708 --- [main] hk.health.common.intf.utils.Logging : DHCIMS[DEBUG] - SFTP_TRANSFER: Uploading C:/FTP_NFS_SHARE/UAT/immu.dh-ha.sync.20200806024505526.20200806024510090.enc.md5 -> /ARRIVED/immu.dh-ha.sync.20200806024505526.20200806024510090.enc.md5.part total: 90 Bytes
2020-08-06 02:45:17.905 INFO 5708 --- [main] hk.health.common.intf.utils.Logging : DHCIMS[INFO] - SFTP_TRANSFER: com.jcraft.jsch.SftpException - No such file or directory(ErrorCode: 2)
2020-08-06 02:45:17.905 INFO 5708 --- [main] hk.health.common.intf.utils.Logging : DHCIMS[INFO] - SFTP_TRANSFER: 2: No such file or directory
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:594)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:475)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:372)
at hk.health.common.intf.utils.SftpConnection.upload(SftpConnection.java:328)
at hk.health.common.intf.CimsMigrationSftp100Application.upload(CimsMigrationSftp100Application.java:277)
at hk.health.common.intf.CimsMigrationSftp100Application.start(CimsMigrationSftp100Application.java:198)
at hk.health.common.intf.CimsMigrationSftp100Application.run(CimsMigrationSftp100Application.java:111)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at hk.health.common.intf.CimsMigrationSftp100Application.main(CimsMigrationSftp100Application.java:106)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
Ниже приведен код для загрузки.
public int upload (Session session, String sourceFilePath, String sourceFileName, String destFilePath) {
try {
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;
SftpProgressMonitor progressMonitor = new SftpProgressMonitor() {
@Override
public void init(int op, java.lang.String src, java.lang.String dest, long max)
{
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", "Uploading " + src + " -> " + dest + " total: " + max + " Bytes");
}
@Override
public boolean count(long bytes)
{
for(int x=0; x < bytes; x++) {
//logger.info("#");
}
return(true);
}
@Override
public void end()
{
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", "Upload completed.");
}
};
// Remove remote .part file if exists before upload
try {
sftpChannel.rm(destFilePath + sourceFileName + ".part");
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", "Deleted existing " + destFilePath + sourceFileName + ".part");
} catch (SftpException e) {
if(e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE){
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", destFilePath + sourceFileName + ".part" + " does not exist");
} else {
logger.WriteLog(log.getPlatform(), "INFO", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", e.getClass().getCanonicalName() + " - " + e.getMessage() + "(ErrorCode: " + e.id + ")" );
}
}
// Upload
sftpChannel.put(sourceFilePath + sourceFileName, destFilePath + sourceFileName + ".part", progressMonitor); // Upload file by .put and rename to .part
// Remove remote data file if exists before rename
try {
sftpChannel.rm(destFilePath + sourceFileName);
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", "Deleted existing " + destFilePath + sourceFileName);
} catch (SftpException e) {
if(e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE){
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", destFilePath + sourceFileName + " does not exist");
} else {
logger.WriteLog(log.getPlatform(), "INFO", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", e.getClass().getCanonicalName() + " - " + e.getMessage() + "(ErrorCode: " + e.id + ")" );
}
}
// Rename
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", "Renaming " + destFilePath + sourceFileName + ".part" + " to " + destFilePath + sourceFileName);
sftpChannel.rename(destFilePath + sourceFileName + ".part", destFilePath + sourceFileName); // Rename the .part to original file name
logger.WriteLog(log.getPlatform(), "DEBUG", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", "Rename completed.");
if(sftpChannel.isConnected()) { sftpChannel.disconnect(); }
if(channel.isConnected()) { channel.disconnect(); }
return 0;
} catch (JSchException e) {
// From channel.connect
logger.WriteLog(log.getPlatform(), "INFO", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", e.getClass().getCanonicalName() + " - " + e.getMessage() );
return 1;
} catch (SftpException e) {
// From sftpChannel.put
logger.WriteLog(log.getPlatform(), "INFO", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", e.getClass().getCanonicalName() + " - " + e.getMessage() + "(ErrorCode: " + e.id + ")" );
StringWriter sw = new StringWriter(); // Debug random error code(2) - 20200729
PrintWriter pw = new PrintWriter(sw); // Debug random error code(2) - 20200729
e.printStackTrace(pw); // Debug random error code(2) - 20200729
String sStackTrace = sw.toString(); // Debug random error code(2) - 20200729
logger.WriteLog(log.getPlatform(), "INFO", als.getProjectCode(), als.getFunctionId(), als.getTransactionId(), als.getOperationId(), "SFTP_TRANSFER", sStackTrace ); // Debug random error code(2) - 20200729
//e.printStackTrace(); // Debug random error code(2) - 20200729
return 1;
}
}