在Windows系统上安装了SSH,并与远程主机(Linux)交换了密钥。我想在windows机器上运行一个JAR来将SCP文件放到Linux机器上。在命令行上使用
"C:/Program Files (X86)/ICW/bin/SCP.exe" -i .ssh/id_rsa <filename> theUser@xxx.xxx.xx.xx:/target/path/<filename>它工作得很好(使用双引号)。
但是当我使用JSch从JAR中运行SCP时,我得到了一个sun.nio.file.InvalidPathException:非法的char <"> at索引.
我的意图是,我必须从FTP主机上以编程方式收集一堆文件(我已经完成了这个部分的工作)。必须将这些文件转发到前面提到的远程主机。FTP主机和远程主机不能直接通信。因此,Windows机器充当一种代理。JAR从FTP服务器获取文件(当前将它们保存在映射中),我希望使用JSch SCP直接将它们放在远程Linux主机上的特定文件夹中。
我该如何解决这个问题?如何解决这一双重报价问题
private void storeFiles() throws IOException {
final JSch jsch = new JSch();
final FileSystem fs = FileSystems.getDefault();
final Path p = fs.getPath( getProperty("scp.key.file.private"));
logger.info("Reading private key from " + getProperty("scp.key.file.private"));
final Session session;
try {
session = jsch.getSession(getProperty("scp.user.name"), getProperty("scp.host.ip"),
Integer.parseInt(getProperty("scp.port")));
jsch.addIdentity(p.toFile().getPath());
final Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
logger.info("Connected to " + getProperty("scp.host.ip") + "...");
vaFiles.forEach((k, v) ->{
// get I/O streams for remote scp
try {
final MessageFormat mf = new MessageFormat(getProperty("scp.command"));
final Object[] commandArgs = new Object[]{getProperty("scp.key.file.private"),
k, getProperty("scp.user.name"),
getProperty("scp.host.ip"),
getProperty("scp.target.path"), k};
final String command = mf.format(commandArgs);
logger.info(command);
final Channel channel;
try {
channel = session.openChannel("exec");
channel.connect();
((ChannelExec)channel).setCommand(command);
// logger.info("Writing " + Arrays.toString(v) + " to SCP channel...");
final OutputStream out = channel.getOutputStream();
out.write(command.getBytes());
out.flush();
out.write(v);
out.close();
channel.disconnect();
} catch (JSchException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}); //end forEach
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
}
}其中vaFiles是Map和scp.command来自属性文件,并且是
scp.command = '\"C\:/Program\u0020Files\u0020(x86)/ICW/bin/scp.exe\"' -i {0} {1} {2}@{3}\:{4}/{5} (我尝试将命令字符串包装为单引号、双引号、不带引号、不带\u 0020、.)
使用MessageFormat填充
{0} = '\"C:/Program\u0020Files\u0020(x86)/ICW/bin/scp.exe\"‘
{1} =文件名
{2} = scp用户名
{3} = scp hist IP地址
{4} =远程主机上的目标路径
{5} =文件名(见{1})
SFTP目前没有选项,只有SCP安装在Windows机器和远程Linux主机上。如果我在做这件事时有完全的误解,我会很感激任何的技术转移,以学习如何做正确的方式。:-)
发布于 2017-10-10 09:20:16
很明显,您正在尝试启动SCP文件从本地Windows机器到远程Linux机器的传输。
但是代码所做的是,它将ssh发送到远程Linux机器,并尝试在那里运行Windows风格的命令C:\Program Files (x86)\ICW\bin\scp.exe。这是行不通的,不管你会用什么样的报价。
- Either use a native Java SCP implementation:http://www.jcraft.com/jsch/examples/ScpTo.java.html
(您将不需要本地OpenSSH安装)
-或者在本地运行scp.exe (您将不需要JSch SSH库)--尽管我根本不推荐这个选项。
发布于 2017-10-10 11:28:04
好的,马丁,谢谢你指引我走向正确的方向。我可能会检查并尝试使用SFTP实现它。目前,您帮助我至少使用SCP实现了一个工作版本(尽管它是一个古老的协议):
private void storeFilesSCP() throws IOException {
final JSch jsch = new JSch();
final FileSystem fs = FileSystems.getDefault();
final Path p = fs.getPath( getProperty("scp.key.file.private"));
logger.info("Reading private key from " + getProperty("scp.key.file.private"));
final Session session;
try {
session = jsch.getSession(getProperty("scp.user.name"), getProperty("scp.host.ip"),
Integer.parseInt(getProperty("scp.port")));
jsch.addIdentity(p.toFile().getPath());
final Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
final UserInfo userInfo = new UserInfo();
session.setUserInfo(userInfo);
session.connect();
logger.info("Connected to " + getProperty("scp.host.ip") + "...");
vaFiles.forEach((k, v) ->{
// get I/O streams for remote scp
try {
final Channel channel;
String command = "scp -t " + getProperty("scp.target.path") + "/" + k + " ";
System.out.println(command);
try {
channel = session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.connect();
command="C0644 " + v.length + " " + k + "\n";
System.out.println(command);
final OutputStream out = channel.getOutputStream();
out.write(command.getBytes());
out.flush();
out.write(v);
out.flush();
out.close();
channel.disconnect();
} catch (JSchException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}); //end forEach
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
}
}https://stackoverflow.com/questions/46650096
复制相似问题