Как я могу запустить свою собственную персонализированную оболочку bash на Java?

#java #linux #bash

#java #linux #bash

Вопрос:

Моя цель — выполнить персонализированное приглашение в оболочке bash в Linux и выполнить заказы. Результат должен быть таким, как на изображении.

введите описание изображения здесь

Итак, я полагаю, я должен начать с чего-то вроде:

 ProcessBuilder builder = new ProcessBuilder();
builder.command("sh");
builder.directory(new File(System.getProperty("user.home")));
Process process = builder.start();
  

или

 String homeDirectory = System.getProperty("user.home");
Process process;
try {
    System.out.print("# MyShell> ");
    process = Runtime.getRuntime().exec(String.format("sh", homeDirectory));
} catch (IOException e) {
    System.err.println("Error en el método exec()");
    e.printStackTrace();
}
  

Управление исключениями.

В основном это запуск персонализированной функциональной командной строки bash на Java и управление сообщениями об ошибках (например, изменение его цвета). Также управление выходом с помощью персонализированного слова, например ‘quit’ вместо ‘exit’.

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

Комментарии:

1. Что произошло, когда вы попробовали свои собственные предложения?

2. Почему вы хотите это сделать? Java предназначена для работы на всех ОС, поэтому в основном у них нет bash, и они будут аварийно завершены или будут иметь приличное сообщение об ошибке. Зачем использовать java для доступа к bash?

3. Что произошло, когда вы попробовали свои собственные предложения? Я не мог заставить это работать.

4. Я не хочу запускать программу в Windows или Mac, просто попробуйте это в Linux.

5. Вы сказали, почему этот другой вопрос не то, что вы хотите. Когда люди спрашивали, что не так с опубликованным вами кодом, вы только говорили: «Я не смог заставить его работать», «он работает не так, как я ожидал», «он не делает то, что я пытаюсь сделать». Я уверен, что это очевидно для вас, но другие люди не могут видеть ваш экран. Представьте, что вы идете к врачу и говорите «это не работает» вместо «я не вижу левым глазом».

Ответ №1:

Эта проблема сложнее, чем кажется, из-за взаимодействия оболочки, терминала и вашей программы.

Учитывая, что требования:

  1. Пользовательская подсказка оболочки
  2. Пользовательские команды
  3. Пусть оболочка работает нормально
  4. Перехватывать вывод программы

Мое предложение:

  1. Выполните настройки со стороны оболочки
  2. Создайте pty, чтобы обмануть программы, думая, что они пишут на терминал. В Java на Linux / Mac простой способ сделать это — с помощью script инструмента.

Вот пример файла конфигурации оболочки myrc :

 export PS1='# MyShell> '
quit() { exit "$@"; }
  

и вот Shell.java , чтобы запустить пользовательскую оболочку:

 import java.io.*;
import java.nio.charset.*;
import java.lang.ProcessBuilder.Redirect;

class Shell {
  public static void main(String[] args) throws IOException {
    ProcessBuilder builder = new ProcessBuilder(
        // Use 'script' to fool programs into thinking stdout is a tty.
        "script", "-q", "/dev/null",
        // Run bash with prompt and command customizations
        "bash", "--rcfile", "myrc"
        );
    builder
      // Get input from the current TTY
      .redirectInput(Redirect.INHERIT)
      // But pipe stdout/stderr to intercept it
      .redirectErrorStream(true)
      .redirectOutput(Redirect.PIPE);

    Process proc = builder.start();
    InputStream input = proc.getInputStream();
    byte[] buffer = new byte[65536];
    int read;

    String search = "world";

    while((read = input.read(buffer, 0, buffer.length)) != -1) {
      // Simplify by assuming we only get text data, and only
      // in buffers large enough to contain the entire search string
      String s = new String(buffer, 0, read, StandardCharsets.UTF_8);
      // Replace search word with a highlighted/colored string.
      s = s.replaceAll(search, "u001B[35m<<$0>>u001B[m");
      System.out.print(s);
    }

    System.out.println("Java program is exiting...");
  }
}
  

Пример сеанса, показывающий пользовательскую подсказку, перехват рабочего текста (делая слово «мир» фиолетовым и окруженным угловыми скобками) и, наконец, пользовательскую quit команду:

 $ javac Shell.java amp;amp; java Shell
# MyShell> echo "hello world"
hello <<world>>
# MyShell> quit
exit
Java program is exiting...
$
  

Комментарии:

1. Прежде всего, спасибо за вашу помощь. К сожалению, я не могу проверить код, так как получаю эту ошибку: script: нераспознанная опция ‘—rcfile’ Я проверил в Google параметры bash, и все должно быть хорошо, но я не знаю, почему программа продолжает выдавать мне эту ошибку.

2. Я тестировал это на macOS script . Судя по чтению справочной страницы Linux, похоже, что так и должно быть "script", "-c", "bash --rcfile myrc", "/dev/null" , хотя я не могу ее протестировать

3. Да, это идеально. Большое вам спасибо. Теперь я собираюсь изучить код, чтобы понять, как это работает. Мне не нравится просто копировать / вставлять 😉