我可以使用JSch从Java成功连接到远程Unix主机,并运行一些基本命令和查看文件等。
问题始于设置环境...当我在一个命令中导出var时,它在下一个命令中不可见,就好像它们在单独的shell中运行一样。我想要做的是模拟在同一个shell中运行的多个命令。
这是我的 executeCommand 方法。它需要先前创建的 openHostSession (下面)创建的com.jcraft.jsch.Session:
public static void executeCommand(Session sess, String cmd, PrintStream pstream)
{
System.out.println("About to execute <" + cmd + ">");
try
{
ChannelExec chnl = (ChannelExec)sess.openChannel("exec");
chnl.setInputStream(null);
chnl.setErrStream(System.err);
chnl.setCommand(cmd);
InputStream in = chnl.getInputStream();
chnl.connect();
byte[] tmp=new byte[1024];
while(true)
{
while(in.available() > 0)
{
int i = in.read(tmp, 0, 1024);
if(i < 0) break;
pstream.print(new String(tmp, 0, i));
}
if(chnl.isClosed())
{
pstream.println("exit-status: " + chnl.getExitStatus());
break;
}
try
{
Thread.sleep(1000);
}
catch(Exception ee){}
}
chnl.disconnect();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
这里是 openHostSession :
public static Session openHostSession(String host, String user, String passwd)
{
JSch jsch=new JSch();
Session rslt = null;
try
{
rslt = jsch.getSession(user, host, 22);
rslt.setConfig("StrictHostKeyChecking", "no");
rslt.setPassword(passwd);
rslt.connect(30000);
}
catch(JSchException jschEx)
{
jschEx.printStackTrace();
}
return rslt;
}
客户端代码
cmd = "export XVAR=abc";
SshUtil.executeCommand(sess, cmd, System.out);
cmd = "echo $XVAR";
SshUtil.executeCommand(sess, cmd, System.out);
输出:
About to execute <export XVAR=abc>
exit-status: 0
About to execute <echo $XVAR>
exit-status: 0
我可以看到系统级环境变量,例如:
cmd = "echo $SHELL";
SshUtil.executeCommand(sess, cmd, System.out);
返回
About to execute <echo $SHELL>
/bin/ksh
退出状态:0
当我发送.profile(cmd = ". ./.profile";)
时,会发生类似的事情,在.profile中设置的vars在下一个命令中不可见。这些命令共享同一个Session但每个都打开自己的Channel。我尝试共享Channels但那没有。
答案 0 :(得分:1)
这是exec频道的工作方式。它对SSH服务器执行单个命令,每个命令执行独立于下一个。就像你做了类似的事情:
# ssh machine 'VAR=tmp; echo $VAR'
foo
# ssh machine 'echo $VAR'
这是两个单独的命令执行,因此环境变量VAR的设置将不会存在于第二个命令的上下文中(因为它们是两个执行的shell)。如果您想使用JSch传输一系列命令,您应该查看ChannelShell类。您可以通过致电:
来利用它ChannelShell chnl = (ChannelShell)sess.openChannel("shell");
这将打开一个长期存在的交互式shell,您可以在其中执行一系列命令,并使第一个命令的结果影响第二个命令。虽然它确实增加了相当多的复杂性,但它并不是“exec”的直接替代品。我建议查看JSch发行版附带的各种示例。他们中的许多人使用openChanell(“shell”)技术,他们可能会帮助你。