如何在Java中运行我自己的个性化bash shell?

huangapple go评论90阅读模式
英文:

How can I run my own personalized bash shell in Java?

问题

我的目标是在Linux的bash shell中执行一个个性化的提示,并执行命令。
结果应该类似于图片中的样子。

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 in exec() method");
    e.printStackTrace();
}

控制异常。

所以基本上是在Java中启动一个个性化的功能性bash提示符,并控制错误消息(比如改变其颜色)。
还可以通过个性化的单词来控制退出,比如使用'quit'代替'exit'。

注意:我不是在尝试执行类似于'tree'或者'ls'之类的脚本或命令,就像在许多其他示例中所看到的那样。我正在寻找一种方法来运行我的个性化bash,并在bash中或接近这个想法的范围内进行所有系统允许的操作。

英文:

My goal is to execute a personalized prompt in a bash shell in linux and to execute orders.
The result should be like in the image.

如何在Java中运行我自己的个性化bash shell?

So I suppose I should start with something like:

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

or

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();
}

Controlling the exceptions.

So basically is to start a personalized functional bash prompt in java and control the error messages (like changing its color).
Also controlling the exit with a personalized word, like 'quit' instead of 'exit'.

Note: I am not trying to execute a script or some commands like 'tree' or 'ls' like in many other examples around here. I'm looking for a way to run my personalized bash and do everything that the system allows me in bash or close to this idea.

答案1

得分: 1

这个问题比表面上看起来要复杂,因为涉及到 shell、终端和您的程序之间的相互作用。

鉴于要求如下:

  1. 自定义 shell 提示符
  2. 自定义命令
  3. 使 shell 正常工作
  4. 拦截程序输出

我的建议是:

  1. 从 shell 方面进行自定义设置
  2. 创建一个伪终端(pty)来欺骗程序,使其认为它们在写入终端。在 Linux/Mac 上的 Java 中,通过 script 工具可以简单实现这一点。

以下是示例 shell 配置文件 myrc

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

以下是启动自定义 shell 的 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(
        // 使用 'script' 欺骗程序,使其认为 stdout 是 tty。
        "script", "-q", "/dev/null",
        // 运行带有提示符和命令自定义的 bash
        "bash", "--rcfile", "myrc"
        );
    builder
      // 从当前 TTY 获取输入
      .redirectInput(Redirect.INHERIT)
      // 但将 stdout/stderr 管道化以拦截它们
      .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) {
      // 简化假设我们只会得到文本数据,并且只会在足够大以包含整个搜索字符串的缓冲区中收到数据
      String s = new String(buffer, 0, read, StandardCharsets.UTF_8);
      // 用高亮/着色的字符串替换搜索词
      s = s.replaceAll(search, "\u001B[35m<<$0>>\u001B[m");
      System.out.print(s);
    }

    System.out.println("Java 程序正在退出...");
  }
}

下面是示例会话,显示了自定义提示符、正常工作的文本拦截(将单词 "world" 改为紫色,并用尖括号括起来),以及最后的自定义 quit 命令:

$ javac Shell.java && java Shell
# MyShell> echo "hello world"
hello <<world>>
# MyShell> quit
exit
Java 程序正在退出...
$
英文:

This problem is more complex than it appears due to the interplay of the shell, the terminal, and your program.

Given that the requirements are:

  1. Custom shell prompt
  2. Custom commands
  3. Have the shell work normally
  4. Intercept the program output

My suggestion is:

  1. Do the customizations from the shell side
  2. Create a pty to fool programs into thinking they're writing to a terminal. In Java on Linux/Mac, a simple way to do this is via the script tool.

Here's an example shell configuration file myrc:

export PS1=&#39;# MyShell&gt; &#39;
quit() { exit &quot;$@&quot;; }

and here's Shell.java to start the custom shell:

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 &#39;script&#39; to fool programs into thinking stdout is a tty.
        &quot;script&quot;, &quot;-q&quot;, &quot;/dev/null&quot;,
        // Run bash with prompt and command customizations
        &quot;bash&quot;, &quot;--rcfile&quot;, &quot;myrc&quot;
        );
    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 = &quot;world&quot;;

    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, &quot;\u001B[35m&lt;&lt;$0&gt;&gt;\u001B[m&quot;);
      System.out.print(s);
    }

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

Example session showing custom prompt, working text interception (making the word "world" purple and surrounded by angle brackets), and finally the custom quit command:

$ javac Shell.java &amp;&amp; java Shell
# MyShell&gt; echo &quot;hello world&quot;
hello &lt;&lt;world&gt;&gt;
# MyShell&gt; quit
exit
Java program is exiting...
$

huangapple
  • 本文由 发表于 2020年10月17日 23:52:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/64404371.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定