在Windows系统上安装了SSH,并与远程主机(Linux)交换密钥。我想在Windows机器上运行一个JAR到SCP机器的SCP文件。 使用
在命令行上执行此操作"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&lt;&#34;&gt;在索引......
目的是我必须从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&lt; String,byte []&gt;和 scp.command 来自属性文件,是
scp.command = '\"C\:/Program\u0020Files\u0020(x86)/ICW/bin/scp.exe\"' -i {0} {1} {2}@{3}\:{4}/{5}
(我试图用单引号括起来,双引号,没有引号,没有\ u0020,......)
使用 MessageFormat 填充
{0} =&#39; \&#34; C:/ Program \ u0020Files \ u0020(x86)/ICW/bin/scp.exe \&#34;&#39;
{1} =文件名
{2} = scp用户名
{3} = scp hist IP地址
{4} =远程主机上的目标路径
{5} =文件名(参见{1})
SFTP目前没有选项,只有SCP安装在Windows机器和远程Linux主机上。 如果我在这方面有完全的误解,我会很感激任何技术转让,以了解如何以正确的方式做到这一点。 : - )
答案 0 :(得分:1)
您显然是在尝试从本地Windows 计算机启动SCP文件传输到远程Linux 计算机。
但是你的代码所做的是,它是ssh到远程Linux 机器并尝试在那里运行Windows风格的命令C:\Program Files (x86)\ICW\bin\scp.exe
。无论你使用什么样的报价,这都行不通。
不要使用SCP,它是一种古老的协议。使用SFTP。所有Linux机器都支持SFTP。 JSch也对SFTP提供原生支持。您不需要任何本地OpenSSH安装。
即使您决定坚持使用SCP,将JSch SSH / SFTP库与本地独立SCP客户端结合起来也毫无意义。
使用本机Java SCP实现:
http://www.jcraft.com/jsch/examples/ScpTo.java.html
(并且您不需要本地OpenSSH安装)
或者在本地运行scp.exe
(并且您不会需要JSch SSH库) - 尽管我根本不推荐这个选项。
答案 1 :(得分:1)
好的,马丁,谢谢你指导我正确的方向。可能我会检查并尝试使用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();
}
}