JSch: переменная, установленная в одной команде, не отображается в следующей (той же сессии)

Я могу успешно подключиться к удаленному хосту Unix с Java с помощью JSch и запустить некоторые основные команды, просмотреть файлы и т. д.

Проблемы начинаются с настройки среды... Когда я экспортирую переменную в одной команде, она не видна в следующей, как будто они работают в разных оболочках. Я хотел бы эмулировать несколько команд, работающих в одной оболочке.

Вот мой метод 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, не видны в следующей команде. Команды используют один и тот же сеанс, но каждая открывает свой собственный канал. Я пытался совместно использовать каналы, но это не сработало.


person amphibient    schedule 19.10.2012    source источник


Ответы (1)


Так работает канал exec. Он выполняет одну команду на сервере SSH, и выполнение каждой команды не зависит от выполнения следующей. Как будто вы сделали что-то вроде:

# ssh machine 'VAR=tmp; echo $VAR'
foo
# ssh machine 'echo $VAR'

Это два отдельных выполнения команд, поэтому установка переменной среды VAR не будет существовать в контексте второй команды (поскольку это две выполняемые оболочки). Если вы хотите передать серию команд с помощью JSch, вам, вероятно, следует изучить класс ChannelShell. Вы можете использовать это, позвонив:

ChannelShell chnl = (ChannelShell)sess.openChannel("shell");

Это откроет многолетнюю интерактивную оболочку, в которой вы можете выполнить ряд команд, и результат первой команды повлияет на вторую команду. Однако это добавляет немного сложности, поэтому это не замена «exec». Я бы рекомендовал ознакомиться с различными примерами, которые поставляются с дистрибутивом JSch. Многие из них используют технику openChanell("shell") и могут вам помочь.

person spdaley    schedule 19.10.2012
comment
Благодарю. я смотрел в ChannelShell, но не мог понять, как запускать в нем команды. любые указатели? спасибо - person amphibient; 19.10.2012
comment
также, когда я делаю . ./.установить путь; someCmdInPath я получаю ksh: someCmdInPath: не найден, но someCmdInPath ЕСТЬ в пути. если я сделаю . ./.установить путь; echo $PATH показывает правильный путь, но не находит двоичные файлы по этому пути - person amphibient; 19.10.2012
comment
есть проблема с поиском скрипта. если я сделаю . ./.profile в первом токене, разделенном точкой с запятой, и echo $TERM во втором, он ничего не отображает для эха, но отображает строку отладки из .profile, чтобы сигнализировать, что он находится в сценарии. то есть, другими словами, он создает скрипт, который устанавливает переменные окружения, но у него возникают проблемы с чтением этих переменных сразу после этого. - person amphibient; 20.10.2012