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

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

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

问题

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

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

或者

  1. String homeDirectory = System.getProperty("user.home");
  2. Process process;
  3. try {
  4. System.out.print("# MyShell> ");
  5. process = Runtime.getRuntime().exec(String.format("sh", homeDirectory));
  6. } catch (IOException e) {
  7. System.err.println("Error in exec() method");
  8. e.printStackTrace();
  9. }

控制异常。

所以基本上是在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:

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

or

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

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

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

以下是启动自定义 shell 的 Shell.java

  1. import java.io.*;
  2. import java.nio.charset.*;
  3. import java.lang.ProcessBuilder.Redirect;
  4. class Shell {
  5. public static void main(String[] args) throws IOException {
  6. ProcessBuilder builder = new ProcessBuilder(
  7. // 使用 'script' 欺骗程序,使其认为 stdout 是 tty。
  8. "script", "-q", "/dev/null",
  9. // 运行带有提示符和命令自定义的 bash
  10. "bash", "--rcfile", "myrc"
  11. );
  12. builder
  13. // 从当前 TTY 获取输入
  14. .redirectInput(Redirect.INHERIT)
  15. // 但将 stdout/stderr 管道化以拦截它们
  16. .redirectErrorStream(true)
  17. .redirectOutput(Redirect.PIPE);
  18. Process proc = builder.start();
  19. InputStream input = proc.getInputStream();
  20. byte[] buffer = new byte[65536];
  21. int read;
  22. String search = "world";
  23. while((read = input.read(buffer, 0, buffer.length)) != -1) {
  24. // 简化假设我们只会得到文本数据,并且只会在足够大以包含整个搜索字符串的缓冲区中收到数据
  25. String s = new String(buffer, 0, read, StandardCharsets.UTF_8);
  26. // 用高亮/着色的字符串替换搜索词
  27. s = s.replaceAll(search, "\u001B[35m<<$0>>\u001B[m");
  28. System.out.print(s);
  29. }
  30. System.out.println("Java 程序正在退出...");
  31. }
  32. }

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

  1. $ javac Shell.java && java Shell
  2. # MyShell> echo "hello world"
  3. hello <<world>>
  4. # MyShell> quit
  5. exit
  6. Java 程序正在退出...
  7. $
英文:

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:

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

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

  1. import java.io.*;
  2. import java.nio.charset.*;
  3. import java.lang.ProcessBuilder.Redirect;
  4. class Shell {
  5. public static void main(String[] args) throws IOException {
  6. ProcessBuilder builder = new ProcessBuilder(
  7. // Use &#39;script&#39; to fool programs into thinking stdout is a tty.
  8. &quot;script&quot;, &quot;-q&quot;, &quot;/dev/null&quot;,
  9. // Run bash with prompt and command customizations
  10. &quot;bash&quot;, &quot;--rcfile&quot;, &quot;myrc&quot;
  11. );
  12. builder
  13. // Get input from the current TTY
  14. .redirectInput(Redirect.INHERIT)
  15. // But pipe stdout/stderr to intercept it
  16. .redirectErrorStream(true)
  17. .redirectOutput(Redirect.PIPE);
  18. Process proc = builder.start();
  19. InputStream input = proc.getInputStream();
  20. byte[] buffer = new byte[65536];
  21. int read;
  22. String search = &quot;world&quot;;
  23. while((read = input.read(buffer, 0, buffer.length)) != -1) {
  24. // Simplify by assuming we only get text data, and only
  25. // in buffers large enough to contain the entire search string
  26. String s = new String(buffer, 0, read, StandardCharsets.UTF_8);
  27. // Replace search word with a highlighted/colored string.
  28. s = s.replaceAll(search, &quot;\u001B[35m&lt;&lt;$0&gt;&gt;\u001B[m&quot;);
  29. System.out.print(s);
  30. }
  31. System.out.println(&quot;Java program is exiting...&quot;);
  32. }
  33. }

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

  1. $ javac Shell.java &amp;&amp; java Shell
  2. # MyShell&gt; echo &quot;hello world&quot;
  3. hello &lt;&lt;world&gt;&gt;
  4. # MyShell&gt; quit
  5. exit
  6. Java program is exiting...
  7. $

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:

确定