我正在开发一个Java应用程序,需要将一个特定的文件SCP到远程计算机。我使用了Jsch库,并按照网站上的ScpTo.java示例做了操作(链接:http://www.jcraft.com/jsch/examples/ScpTo.java)。
然而,在应用程序中,SCP命令会出现问题。因此,我尝试在Cygwin终端中手动运行SCP命令。
我的命令看起来像这样:
命令的输出内容为:
然而,在应用程序中,SCP命令会出现问题。因此,我尝试在Cygwin终端中手动运行SCP命令。
我的命令看起来像这样:
scp -t /home/user/test.csv
C0644 197171 C:\Users\user\Documents\test.csv
命令的输出内容为:
C:\Users\user\Documents\test.csv 0% 0 0.0KB/s - stalled -
看起来它好像只是这么做了。现在我认为这可能是防火墙问题,因此我尝试了几台其他远程机器,它们仍然给了我相同的问题。
有任何处理这种问题的想法吗?
非常感谢,
Joe
编辑:以下是Java代码:
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;
class HPCConnector
{
private static String username = "username";
private static String host = "host.edu";
JSch jsch;
Session session;
UserInfo ui;
public HPCConnector() throws JSchException
{
jsch = new JSch();
session = jsch.getSession(username, host, 22);
ui = new HPCUserInfo();
session.setUserInfo(ui);
}
public boolean validateConnection()
{
boolean status = true;
try {
session.connect();
if (status)
return status;
} catch (JSchException e) {
e.printStackTrace();
status = false;
}
return status;
}
public static class HPCUserInfo implements UserInfo, UIKeyboardInteractive
{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str)
{
Object[] options={ "Yes", "No" };
int foo=JOptionPane.showOptionDialog(null, str,"Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,null, options, options[0]);
return foo==0;
}
String passwd;
JTextField passwordField=(JTextField)new JPasswordField(20);
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message)
{
Object[] ob={passwordField};
int result=
JOptionPane.showConfirmDialog(null, ob, message,
JOptionPane.OK_CANCEL_OPTION);
if(result==JOptionPane.OK_OPTION)
{
passwd=passwordField.getText();
return true;
}
else{ return false; }
}
public void showMessage(String message)
{
JOptionPane.showMessageDialog(null, message);
}
final GridBagConstraints gbc = new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0);
private Container panel;
public String[] promptKeyboardInteractive(String destination,String name,String instruction,String[] prompt,boolean[] echo)
{
panel = new JPanel();
panel.setLayout(new GridBagLayout());
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
panel.add(new JLabel(instruction), gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.RELATIVE;
JTextField[] texts=new JTextField[prompt.length];
for(int i=0; i<prompt.length; i++)
{
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.weightx = 1;
panel.add(new JLabel(prompt[i]),gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = 1;
if(echo[i])
{
texts[i]=new JTextField(20);
}
else
{
texts[i]=new JPasswordField(20);
}
panel.add(texts[i], gbc);
gbc.gridy++;
}
if(JOptionPane.showConfirmDialog(null, panel, destination+": "+name,JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE) ==JOptionPane.OK_OPTION)
{
String[] response=new String[prompt.length];
for(int i=0; i<prompt.length; i++)
{
response[i]=texts[i].getText();
}
return response;
}
else
{
return null; // cancel
}
}
}
public void transferToHPC(File spreadsheet) throws JSchException
{
OutputStream out = null;
InputStream in = null;
String command = "scp -t /home/user/" + spreadsheet.getName();
Channel channel = session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
try{
out = channel.getOutputStream();
in = channel.getInputStream();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println(command);
long fileSize= spreadsheet.length();
channel.connect();
command = "C0644 " + fileSize + " " + spreadsheet.getAbsolutePath() + "\n";
try {
if(checkAck(in)!=0){
System.exit(0);
}
out.write(command.getBytes());
out.flush();
FileInputStream fis = new FileInputStream(spreadsheet);
byte[] buffer = new byte[1024];
while (true)
{
int length = fis.read(buffer, 0, buffer.length);
if (length <= 0)
break;
out.write(buffer, 0, 1);
}
fis.close();
fis = null;
System.out.println(command);
buffer[0] = 0;
out.write(buffer, 0, 1);
out.flush();
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
channel.disconnect();
session.disconnect();
}
static int checkAck(InputStream in) throws IOException{
int b=in.read();
// b may be 0 for success,
// 1 for error,
// 2 for fatal error,
// -1
if(b==0) return b;
if(b==-1) return b;
if(b==1 || b==2){
StringBuffer sb=new StringBuffer();
int c;
do {
c=in.read();
sb.append((char)c);
}
while(c!='\n');
if(b==1){ // error
System.out.print(sb.toString());
}
if(b==2){ // fatal error
System.out.print(sb.toString());
}
}
return b;
}
}
编辑2:控制台上没有出现任何异常,而使我感到困扰的主要函数是transferToHPC(文件电子表格)
编辑3:好吧,最终我放弃了这个问题。能够使用JSch的Sftp类并且它的工作方式符合我的意图。
我做了更多的阅读并阅读了Kenster的答案,我认为我应该保留-t标志供scp内部处理 :)谢谢大家!