Некоторые команды Unix завершаются с ошибкой, не найдены при выполнении через Java с использованием JSch, даже с включенным setPty.

Я создаю приложение для Android, которое отправляет команды на терминал Linux на устройстве. Я могу получить правильный вывод при использовании команды «ls», однако устройство не дает мне никакого вывода, когда я использую «ifconfig» или «iwconfig». Используя Tera Term, я убедился, что эти команды работают. Я попытался включить ((ChannelExec)channel).setPty(true);, чтобы исправить это, однако терминал по-прежнему не распознает команду. Добавление этой строки кода также изменяет мой вывод для команды «ls» на что-то, что я не узнаю.

Это мой код JSch:

package com.example.riot94.whizpacecontroller;
import android.os.AsyncTask;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;

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;
/**
 * Created by riot94 on 1/6/2017.
 */

public class JSchConnectionProtocol extends AsyncTask<String, Void, String>{
    private String host;
    private String user;
    private String password;

    public JSchConnectionProtocol(String h, String u, String p){
        host = h;
        user = u;
        password = p;
    }

    @Override
    protected String doInBackground(String... command) {
        String output = "";
        try{
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            JSch jsch = new JSch();
            Session session=jsch.getSession(user, host, 22);
            session.setPassword(password);
            session.setConfig(config);
            session.setTimeout(10000);
            Log.d("CONNECTION", "Attempting to connect to " + host + " as user: " + user);
            session.connect();
            Log.d("CONNECTION", "Connected to " + host + " as user: " + user);

            Channel channel=session.openChannel("exec");
            ((ChannelExec)channel).setPty(true);
            ((ChannelExec)channel).setCommand(command[0]);
            channel.setInputStream(null);
            ((ChannelExec)channel).setErrStream(System.err);

            output = printOutputAfterXMilliSeconds(channel,1000);

            channel.disconnect();
            session.disconnect();
            Log.d("DONE","DONE");
        }catch(Exception e){
            e.printStackTrace();
        }
        return output;
    }

    private String printOutputAfterXMilliSeconds(Channel channel, int ms) throws IOException, JSchException {
        InputStream in=channel.getInputStream();
        channel.connect();
        String totalOutput = "";
        byte[] tmp=new byte[1024];
        while(true){
            while(in.available()>0){
                int i=in.read(tmp, 0, 1024);
                if(i<0)break;
                String output = new String(tmp, 0, i);
                totalOutput += output;
                Log.d("OUTPUT", output);
            }

            if(channel.isClosed()){
                Log.d("EXIT_STAT","exit-status: "+channel.getExitStatus());
                break;
            }

            try{
                Log.d("PRE-SLEEP","About to sleep");
                Thread.sleep(ms);
                //channel.sendSignal("2");
                Log.d("POST-SLEEP","Slept and woken");
            }catch(Exception ee){
                ee.printStackTrace();
                channel.disconnect();
            }
        }
        return totalOutput;
    }

}

Мое приложение для Android получает пустую строку в своей деятельности, когда я вхожу

iwconfig

без ((ChannelExec)channel).setPty(true);. С ним мой вывод:

ash: iwconfig: не найдено
статус выхода: 127

Я получаю аналогичный результат с

ifconfig

Мой вывод команды «ls» с ((ChannelExec)channel).setPty(true);:

[1;34mGUI[0m                            [1;32mmeter.sh[0m
[1;32mReadme4Gui[0m                     [0;0mmeter_iplist.txt[0m
[1;32mami_concentrator_ETH_20120413[0m  [0;0mmeter_list.txt[0m
[1;32mami_demo_qingjun[0m               [0;0mroute.sh[0m
[1;32mami_festtech[0m                   [1;32mscript.sh[0m
[1;32mami_mac[0m                        [1;32msetGateway.sh[0m
[1;32mami_qingjun[0m                    [1;32mspectrmgmt[0m
[1;32mbootup.sh[0m                      [1;32msystem.sh[0m
[1;32mconcentrator.sh[0m                [1;32mtemp1.sh[0m
[1;32mdisFreq.sh[0m                     [1;32mtest.sh[0m
[1;32mdisLinkQuality.sh[0m              [1;32mtest1.sh[0m

Мой вывод команды «ls» без ((ChannelExec)channel).setPty(true);:

GUI
Readme4Gui
ami_concentrator_ETH_20120413
ami_demo_qingjun
ami_festtech
ami_mac
ami_qingjun
bootup.sh
concentrator.sh
disFreq.sh
disLinkQuality.sh
meter.sh
meter_iplist.txt
meter_list.txt
route.sh
script.sh
setGateway.sh
spectrmgmt
system.sh
temp1.sh
test.sh
test1.sh

Я не уверен, что я делаю неправильно, как я могу это исправить, чтобы получить правильный вывод для обеих команд iwconfig/ifconfig и ls?


person Ryan T.    schedule 06.06.2017    source источник
comment
Используйте SSH-клиент командной строки (например, ssh в *nix или plink в Windows) для запуска следующих команд: ssh -T username@host ifconfig, ssh -t username@host ifconfig, echo ifconfig | ssh -t username@host и echo ifconfig | ssh -T username@host. Какие из них работают, а какие нет?   -  person Martin Prikryl    schedule 06.06.2017
comment
Я правильно понимаю, что с ((ChannelExec)channel).setPty(true); вы получаете то же поведение с ifconfig, что и без setPty?   -  person Martin Prikryl    schedule 06.06.2017
comment
Извините, я не понимаю первый комментарий, я должен запустить ssh -T username@host ifconfig и другие команды по SSH, не так ли? Будет ли работать VM Linux или Git Bash? username будет именем пользователя моего компьютера, а host будет IP-адресом, к которому я пытаюсь подключиться, верно? Что касается ifconfig, он дает мне тот же результат ash: ifconfig: not found, когда я запускаю код отдельно в Eclipse. В приложении для Android без ((ChannelExec)channel).setPty(true); вывод представляет собой пустую строку "", тогда как с ((ChannelExec)channel).setPty(true); вывод ash: ifconfig: not found   -  person Ryan T.    schedule 07.06.2017
comment
Да, VM linux или Git bash подойдут. Но на самом деле вы можете использовать команды в SSH-терминале самого сервера (подключившись обратно к хосту). username и host — это те же имя пользователя и хост, которые указаны в вашем Java-коде. - Что касается ifconfig, он дает мне тот же вывод: ifconfig: not found, когда я запускаю код отдельно в Eclipse - Не знаю, на что вы ссылаетесь. Вы действительно пробовали команды, которые я предложил в Eclipse? И все они дают вам это сообщение об ошибке?   -  person Martin Prikryl    schedule 07.06.2017
comment
Я отредактировал свой вопрос с результатами команд, которые вы предложили выше. Я не слишком уверен, что делают эти команды, хотя   -  person Ryan T.    schedule 07.06.2017
comment
Я не хотел, чтобы вы запускали их в JSch. - Как вы запускаете Git Bash? Я не понимаю проблемы с Псевдо-терминал не будет выделен, потому что stdin не является терминалом, когда я запускаю команды из окна Git Bash. - Если вы работаете в Windows, вы можете использовать Plink вместо ssh из cmd.exe окна консоли. - Почему у вас тайм-аут соединения? Доступен ли хост Linux с сайта, на котором вы запускаете команду?   -  person Martin Prikryl    schedule 07.06.2017
comment
Моя командная строка не распознает Plink или plink. В Git Bash я просто ввожу приведенные выше команды с соответствующими host и user. Да, хост Linux доступен с сайта.   -  person Ryan T.    schedule 07.06.2017
comment
the.earth.li/~sgtatham/putty/latest/w32/ plink.exe   -  person Martin Prikryl    schedule 07.06.2017
comment
Я не могу запустить файл, приложение почти мгновенно закрывается, когда я пытаюсь его запустить.   -  person Ryan T.    schedule 07.06.2017
comment
Это консольное приложение, его нужно запускать из окна консоли (cmd.exe).   -  person Martin Prikryl    schedule 07.06.2017
comment
Я получаю сообщение об ошибке: ash: ifconfig: not found   -  person Ryan T.    schedule 07.06.2017
comment
Для всех четырех команд? (замените ssh на plink в командах).   -  person Martin Prikryl    schedule 07.06.2017
comment
Я не уверен, как запустить последние 2 команды с plink, но первые 2 команды дают мне ash: ifconfig: not found   -  person Ryan T.    schedule 07.06.2017
comment
Для ясности я ввел E:/plink -t [email protected] ifconfig и E:/plink -t [email protected] ifconfig   -  person Ryan T.    schedule 07.06.2017
comment
Точно так же, как и с ssh: echo ifconfig | E:\plink -t username@host   -  person Martin Prikryl    schedule 07.06.2017
comment
Последние 2 команды дают мне: 'E:' is not recognised as an internal or external command, operable program or batch file.   -  person Ryan T.    schedule 07.06.2017
comment
Покажите мне скриншот всего окна консоли с сообщением об ошибке.   -  person Martin Prikryl    schedule 07.06.2017
comment
Это должно выглядеть так: i.stack.imgur.com/l3Vxg.png   -  person Martin Prikryl    schedule 07.06.2017
comment
Скриншот: imgur.com/a/I6h68   -  person Ryan T.    schedule 07.06.2017
comment
Загрузите и запустите PuTTY.exe, в поле Имя хоста введите username@host, перейдите в раздел Подключение › SSH › Kex и переместите группу Диффи-Хеллмана 1 над -- предупреждение ниже здесь -- строка. И сохраните настройки, чтобы сохранить сеанс. Попробуйте подключиться. Подтвердите ключ хоста. А затем с помощью plink выполните echo ifconfig | E:\plink store_session_name -t-T).   -  person Martin Prikryl    schedule 07.06.2017
comment
Я получаю сообщение об ошибке -ash: plink: not found. Должен ли я загружать plink на устройство, к которому пытаюсь подключиться? Если да, есть ли способ перенести приложение с моего компьютера на устройство? Устройство не может быть подключено к Интернету.   -  person Ryan T.    schedule 08.06.2017
comment
Покажите нам снимок экрана TeraTerm или PuTTY, показывающий, как вы выполняете файл ifconfig.   -  person Martin Prikryl    schedule 08.06.2017
comment
Скриншот: imgur.com/a/sy5Dq   -  person Ryan T.    schedule 08.06.2017
comment
Нет, пожалуйста, просто команду ifconfig.   -  person Martin Prikryl    schedule 08.06.2017
comment
Скриншот   -  person Ryan T.    schedule 08.06.2017
comment
В PuTTY, если вы наберете which ifconfig, что вы получите?   -  person Martin Prikryl    schedule 08.06.2017
comment
я получаю /sbin/ifconfig   -  person Ryan T.    schedule 08.06.2017
comment
Попробуйте использовать /sbin/ifconfig в своем setCommand.   -  person Martin Prikryl    schedule 08.06.2017
comment
Оно работает! Благодарю вас! Итак, проблема заключалась в том, что я не обращался к каталогу, в котором находилась команда, верно?   -  person Ryan T.    schedule 08.06.2017


Ответы (1)


Ваш сервер/оболочка каким-то образом неправильно настроен. Он неправильно устанавливает PATH, когда сеанс оболочки не запущен. Вот почему двоичные файлы ifconfig/iwconfig не могут быть найдены.

Либо исправьте свои сценарии запуска, чтобы правильно установить PATH для всех ситуаций. Или используйте полный путь к файлу ifconfig/iwconfig.

Чтобы найти полный путь, откройте обычный сеанс оболочки с помощью клиента SSH и введите:

which ifconfig

Аналогичную проблему см. в разделе Некоторые команды Unix завершаются с ошибкой... not found при выполнении через Java с использованием JSch.

person Martin Prikryl    schedule 08.06.2017