Как я могу программно выполнить все возможные команды unix (shell) в Android?

1

У меня есть этот файл.php, отправляющий команды моему приложению для Android:

Изображение 174551

Я пробовал работать с:

Runtime.getRuntime().exec(commandLine);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

но команды echo, pwd и некоторые другие не работают.

Я получаю следующее исключение:

java.io.IOException: Error running exec(). Command: [pwd] Working Directory: null Environment: null

Насколько я понимаю, это потому, что нет оболочки оболочки.

Затем я попытался записать в файл.sh команду, которую я хочу, а затем выполнить команду следующим образом:

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("sh /runCmds/shTest.sh");
InputStream is = proc.getInputStream();

и решена проблема с pwd, echo и большинством команд.

Но позже я понял, что хочу сохранить состояние команд, которые я выполняю. Например, я хочу изменить каталог (cd data) и выполнить команду mkdir Apoel

И вот когда я сталкиваюсь с моей проблемой. Что делать?

Я придумал еще одну идею:

Создайте сценарий оболочки (.sh) и каждый раз, когда пользователь хочет выполнить команду, добавьте в него новую команду (и снова запустите скрипт дыр (.sh)). Но я думаю, что это не очень хороший способ сделать это!

Есть ли простой способ? Могу ли мое приложение легко открыть терминал?

Вот код, который я нашел для эмулятора терминала, но он слишком сложный!

https://github.com/jackpal/Android-Terminal-Emulator

Теги:
android-ndk
android-intent

2 ответа

0

Интерактивная оболочка остается той, которая остается запущенной, ожидая новых команд, которые она получает от stdin, при этом она выводит на stdout и stderr - в результате среда, включая любые изменения, сохраняется на время сеанса. Чтобы оболочка была полезной для пользователя, stdin, stoud, stderr необходимо подключить к пользователю - через консоль, последовательную линию или xterm и т.д.

На Android обычно используется то, что вы делаете, подключаетесь к трубам, соответствующим stdin, stdout, stderr для созданного вами процесса оболочки, и используйте их для ввода команд, предоставляемых вашей java-программой, и принимайте вывод для вашей программы для интерпретации/дисплей.

Идея создания сценария и его запуска будет работать только в том случае, когда все команды вводятся до того, как они выполняются.

  • 0
    Как я могу сохранить открытую сессию ? Вы сказали: все команды вводятся до выполнения любой из них. Вы можете объяснить, может быть, на примере? Вы имеете в виду что-то вроде этого: touch abc; cp abc def; cd /; ?
  • 0
    Вы оставляете сеанс открытым, сохраняя одну и ту же копию оболочки и взаимодействуя с ней через каналы. Если вы использовали свою идею сценария, вам нужно было бы поместить все команды в сценарий (да, это немного похоже на размещение их в одной строке с;), прежде чем вы запустили (и получили выходные данные) любую из них - в какой момент вы бы больше не были интерактивными. Возможно, пришло время еще раз попытаться разобраться в источниках эмулятора терминала.
0

Во-первых, некоторый фон. В любой системе Posix в оболочке есть 2 типа команд:

  1. Внутренние команды (pwd, cd, echo)
  2. внешние команды (ls, cp, mv, иногда также эхо)

Все команды контекста каталога (cd, pwd и т.д.) Являются командами, реализованными внутри оболочки и, следовательно, требуют, чтобы оболочка оставалась запущенной, если изменения должны удерживаться (например, cd/data/local/tmp).

С другой стороны, внешние команды автономны и могут выполняться автономно, но приобретают свой контекст каталога из своего родительского процесса (в большинстве случаев - оболочки).

Теперь решить проблему. Да, использование сценария - хорошая идея, но это очень сложно реализовать, так как для этого требуется накладные расходы на редактирование файлов. Однако мы можем использовать оболочку для создания сценария "на лету" и выполнить его с помощью опции -c. Например:

/system/bin/sh -c 'cd /data/local/tmp; touch abc; cp abc def; cd /; rm /data/local/tmp/abc'

В летнее время:

String sPrefix="/system/bin/sh -c 'cd someplace;";
String sInputCmd=getCommand(); // this is simulating your command input
String sPostfix="'";

Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(sPrefix+sInputCmd+sPostfix); // sh -c 'cd someplace; echo do something'
InputStream is = proc.getInputStream();

Однако это не дает нам возможности установить контекст каталога, поэтому нам нужно имитировать это. Контексты каталогов могут быть добавлены с помощью метода Runtime.exec(String, String [] envp, File dir). При этом у нас есть возможность поддерживать контекст каталога между командами. Но как мы на самом деле это делаем? Одним из решений является добавление команды pwd к команде и вывод последней строки в качестве нового контекста каталога. таким образом

String sPath = "/"; // start in root directory
String sPrefix = "/system/bin/sh -c 'cd someplace;";
String sInputCmd; // this is simulating your command input
String sPostfix = ";echo;pwd'";
Runtime rt = Runtime.getRuntime();
while(!(sInputCmd=getCommand()).equals("")) {
    File dir= new File(sPath);
    Process proc = rt.exec(sPrefix+sInputCmd+sPostfix, NULL, dir);
    InputStream is = proc.getInputStream();
    // Do processing on input.
    sPath= last_line_of_is ;
}

Наконец, последним вариантом является интеграция одного из эмуляторов терминала в ваше приложение.

[1] http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#exec%28java.lang.String,%20java.lang.String%5B%5D,%20java.io.File% 29

  • 0
    Вы имеете в виду / system / bin / sh -c 'команды здесь', а не su! Лучше использовать абсолютный путь.
  • 0
    Андреас, ты прав, я имел в виду ш, а не су. Я сделал исправление.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню