0

我能够使用 JSch 从 Java 成功连接到远程 Unix 主机并运行一些基本命令和查看文件等。

问题从设置环境开始......当我在一个命令中导出一个 var 时,它在下一个命令中不可见,就好像它们在单独的 shell 中运行一样。我想做的是模拟在同一个 shell 中运行的多个命令。

这是我的executeCommand方法。它需要一个以前创建的 com.jcraft.jsch.Session 由openHostSession创建(如下):

    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 中设置的变量在下一个命令中不可见。这些命令共享相同的会话,但每个都打开自己的频道。我尝试共享频道,但没有这样做。

4

1 回答 1

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") 技术,他们可能会帮助你。

于 2012-10-19T18:39:19.700 回答