"Remote Acknowledge failed: scp: ambiguous target" 在 Windows 机器上使用 "scp" 上传文件时,在 Linux 和 Mac 上工作
"Remote Acknowledge failed: scp: ambiguous target" while uploading files using "scp" from Windows machine, while it works on Linux and Mac
我正在尝试 运行 一个测试用例,该用例基本上将文件从我的机器复制到模拟服务器 运行 在 docker 中。同样的测试在 Mac 和 Ubuntu 上运行良好。但是在 Windows 上,它因以下错误而失败:-
Exception while executing command on remote SSH server
java.lang.RuntimeException: Exception while executing command on remote SSH server
at com.org.implementation.RemoteCommandWrapper.runSshCommandWithTimeout(RemoteCommandWrapper.java:53)
at com.org.implementation.RemoteCommandWrapper.copyLocalToRemote(RemoteCommandWrapper.java:121)
...
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: Remote Acknowledge failed: scp: ambiguous target
at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2022)
at com.org.implementation.cboserver.RemoteCommandWrapper.runSshCommandWithTimeout(RemoteCommandWrapper.java:49)
... 92 more
Caused by: java.lang.RuntimeException: Remote Acknowledge failed: scp: ambiguous target
at com.org.implementation.RemoteCommandWrapper.checkAck(RemoteCommandWrapper.java:174)
at com.org.implementation.RemoteCommandWrapper.waitForFileCopied(RemoteCommandWrapper.java:136)
at com.org.implementation.RemoteCommandWrapper.lambda$copyLocalToRemote(RemoteCommandWrapper.java:124)
at com.org.implementation.RemoteCommandWrapper.tryToExecuteCommand(RemoteCommandWrapper.java:68)
at com.org.implementation.RemoteCommandWrapper.lambda$runSshCommandWithTimeout[=15=](RemoteCommandWrapper.java:45)
...
RemoteCommand.java:-
public void copyLocalToRemote(Session session, Path localPath, Path remotePath, String fileName) {
log.info("localPath: {}",localPath); //localPath:C:\Users\myuser\project1\src\test\resourcesf9cce18-362e-4973-a26b-730131841d7b
log.info("remotePath: {}",remotePath); // remotePath:\
log.info("fileName: {}",fileName);// fileName: CustomFile.zip
String copyCommand = createCopyCommand(remotePath);
runSshCommandWithTimeout(session,
copyCommand,
(channel, in, out) -> {
waitForFileCopied(channel, in, out, localPath, fileName);
return null;
});
}
private String createCopyCommand(Path remotePath) {
return String.format("scp -p -t %s\n", remotePath);
}
private void waitForFileCopied(Channel channel, InputStream in, OutputStream out, Path localPath, String fileName) {
Path from = localPath.resolve(fileName);
try (FileInputStream fis = new FileInputStream(from.toString())) {
checkAck(in);
setFileAccess(from, out, in);
fis.transferTo(out);
// send '[=16=]'
out.write(new byte[]{0}, 0, 1);
out.flush();
checkAck(in);
} catch (IOException e) {
throw new RuntimeException("Error copying custom file", e);
}
}
@SneakyThrows
private void checkAck(InputStream in){
int b = in.read();
if (b == 0) return;
if (b < 0) throw new RuntimeException("Remote Acknowledge failed: " + Integer.valueOf(b));
StringBuilder sb = new StringBuilder();
int c;
do {
c = in.read();
sb.append((char) c);
}
while (c != '\n');
throw new RuntimeException("Remote Acknowledge failed: " + sb.toString());
}
<T> T runSshCommandWithTimeout(final Session session, String command, RemoteResultFactory<T> resultFactory) {
CompletableFuture<T> future = CompletableFuture.supplyAsync(
() -> tryToExecuteCommand(session, command, resultFactory)
);
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
throw new RemoteTimeoutException(String.format("Timeout while executing command on remote SSH server: %d ms", timeoutMs));
} catch (Exception e) {
throw new RuntimeException("Exception while executing command on remote SSH server", e);
}
}
private <T> T tryToExecuteCommand(Session session, String command, RemoteResultFactory<T> resultFactory) {
Channel channel = null;
try {
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
// TODO handle extInputStream (error stream)
try (InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream()) {
channel.connect();
return resultFactory.getResult(channel, in, out);
}
} catch (JSchException | IOException e) {
throw new RuntimeException("Exception while executing command on remote SSH server", e);
} finally {
if (channel != null) {
channel.disconnect();
}
session.disconnect();
}
}
在 Google 上搜索此错误时,我可以理解 scp
无法识别目标目的地,这也应该是 Window 路径的问题,或者可能是因为"/"
或 "\"
因为同一测试正在基于 Linux 的文件系统(以及 Mac)上工作。
我无法弄清楚确切的问题以及解决方法。
有人可以建议从中恢复吗?
谢谢
远程路径必须是/
,而不是\
。
并且 createCopyCommand
的参数不能是 Path
,就像 Windows 一样,这会将 /
转换为 \
。
我正在尝试 运行 一个测试用例,该用例基本上将文件从我的机器复制到模拟服务器 运行 在 docker 中。同样的测试在 Mac 和 Ubuntu 上运行良好。但是在 Windows 上,它因以下错误而失败:-
Exception while executing command on remote SSH server
java.lang.RuntimeException: Exception while executing command on remote SSH server
at com.org.implementation.RemoteCommandWrapper.runSshCommandWithTimeout(RemoteCommandWrapper.java:53)
at com.org.implementation.RemoteCommandWrapper.copyLocalToRemote(RemoteCommandWrapper.java:121)
...
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: Remote Acknowledge failed: scp: ambiguous target
at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2022)
at com.org.implementation.cboserver.RemoteCommandWrapper.runSshCommandWithTimeout(RemoteCommandWrapper.java:49)
... 92 more
Caused by: java.lang.RuntimeException: Remote Acknowledge failed: scp: ambiguous target
at com.org.implementation.RemoteCommandWrapper.checkAck(RemoteCommandWrapper.java:174)
at com.org.implementation.RemoteCommandWrapper.waitForFileCopied(RemoteCommandWrapper.java:136)
at com.org.implementation.RemoteCommandWrapper.lambda$copyLocalToRemote(RemoteCommandWrapper.java:124)
at com.org.implementation.RemoteCommandWrapper.tryToExecuteCommand(RemoteCommandWrapper.java:68)
at com.org.implementation.RemoteCommandWrapper.lambda$runSshCommandWithTimeout[=15=](RemoteCommandWrapper.java:45)
...
RemoteCommand.java:-
public void copyLocalToRemote(Session session, Path localPath, Path remotePath, String fileName) {
log.info("localPath: {}",localPath); //localPath:C:\Users\myuser\project1\src\test\resourcesf9cce18-362e-4973-a26b-730131841d7b
log.info("remotePath: {}",remotePath); // remotePath:\
log.info("fileName: {}",fileName);// fileName: CustomFile.zip
String copyCommand = createCopyCommand(remotePath);
runSshCommandWithTimeout(session,
copyCommand,
(channel, in, out) -> {
waitForFileCopied(channel, in, out, localPath, fileName);
return null;
});
}
private String createCopyCommand(Path remotePath) {
return String.format("scp -p -t %s\n", remotePath);
}
private void waitForFileCopied(Channel channel, InputStream in, OutputStream out, Path localPath, String fileName) {
Path from = localPath.resolve(fileName);
try (FileInputStream fis = new FileInputStream(from.toString())) {
checkAck(in);
setFileAccess(from, out, in);
fis.transferTo(out);
// send '[=16=]'
out.write(new byte[]{0}, 0, 1);
out.flush();
checkAck(in);
} catch (IOException e) {
throw new RuntimeException("Error copying custom file", e);
}
}
@SneakyThrows
private void checkAck(InputStream in){
int b = in.read();
if (b == 0) return;
if (b < 0) throw new RuntimeException("Remote Acknowledge failed: " + Integer.valueOf(b));
StringBuilder sb = new StringBuilder();
int c;
do {
c = in.read();
sb.append((char) c);
}
while (c != '\n');
throw new RuntimeException("Remote Acknowledge failed: " + sb.toString());
}
<T> T runSshCommandWithTimeout(final Session session, String command, RemoteResultFactory<T> resultFactory) {
CompletableFuture<T> future = CompletableFuture.supplyAsync(
() -> tryToExecuteCommand(session, command, resultFactory)
);
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
throw new RemoteTimeoutException(String.format("Timeout while executing command on remote SSH server: %d ms", timeoutMs));
} catch (Exception e) {
throw new RuntimeException("Exception while executing command on remote SSH server", e);
}
}
private <T> T tryToExecuteCommand(Session session, String command, RemoteResultFactory<T> resultFactory) {
Channel channel = null;
try {
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
// TODO handle extInputStream (error stream)
try (InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream()) {
channel.connect();
return resultFactory.getResult(channel, in, out);
}
} catch (JSchException | IOException e) {
throw new RuntimeException("Exception while executing command on remote SSH server", e);
} finally {
if (channel != null) {
channel.disconnect();
}
session.disconnect();
}
}
在 Google 上搜索此错误时,我可以理解 scp
无法识别目标目的地,这也应该是 Window 路径的问题,或者可能是因为"/"
或 "\"
因为同一测试正在基于 Linux 的文件系统(以及 Mac)上工作。
我无法弄清楚确切的问题以及解决方法。
有人可以建议从中恢复吗?
谢谢
远程路径必须是/
,而不是\
。
并且 createCopyCommand
的参数不能是 Path
,就像 Windows 一样,这会将 /
转换为 \
。