如何 运行 standalone/interactive Spring 引导 CRaSH Shell 应用程序?
How to run a standalone/interactive Spring Boot CRaSH Shell application?
我想要 运行 一个 Spring 嵌入 CRaSH shell 的引导应用程序,但我想要 CRaSH shell 而不是通过 SSH/Telnet 访问] 在当前控制台(即 direct/standalone)中启动而无需任何密码,只要 Spring 完成所有 bean 的初始化。
当用户键入 exit
或按 Ctrl+D 时,应用程序应关闭。
另外,应该禁用 SSH 和 Telnet 支持。
PS。如果应用程序可以从 stdin 读取命令,例如
./crshapp < somefile.cmd
cat somefile.cmd | ./crshapp
我遇到了同样的问题,所以我实现了以下代码以附加到由引导配置的 运行 shell。
我通过复制 org.crsh.standalone.CRaSH 中的一些代码来做到这一点,这些代码加载了一个独立的 shell。
import org.crsh.console.jline.JLineProcessor;
import org.crsh.console.jline.Terminal;
import org.crsh.console.jline.TerminalFactory;
import org.crsh.console.jline.console.ConsoleReader;
import org.crsh.plugin.PluginLifeCycle;
import org.crsh.shell.Shell;
import org.crsh.shell.ShellFactory;
import org.crsh.util.InterruptHandler;
import org.fusesource.jansi.AnsiConsole;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.CommandLineRunner;
import java.io.*;
public class InteractiveShellRunner implements CommandLineRunner, InitializingBean, DisposableBean {
final private PluginLifeCycle crshBootstrapBean;
private Shell shell;
private Terminal term;
public InteractiveShellRunner(PluginLifeCycle crshBootstrapBean) {
this.crshBootstrapBean = crshBootstrapBean;
}
@Override
public void afterPropertiesSet() throws Exception {
ShellFactory shellFactory = crshBootstrapBean.getContext().getPlugin(ShellFactory.class);
shell = shellFactory.create(null);
}
@Override
public void destroy() throws Exception {
try {
if (term != null) {
term.restore();
}
} catch (Exception ignore) {
}
}
@Override
public void run(String... args) throws Exception {
if (shell != null) {
term = TerminalFactory.create();
//
String encoding = jline.internal.Configuration.getEncoding();
// Use AnsiConsole only if term doesnt support Ansi
PrintStream out;
PrintStream err;
boolean ansi;
if (term.isAnsiSupported()) {
out = new PrintStream(new BufferedOutputStream(term.wrapOutIfNeeded(new FileOutputStream(FileDescriptor.out)), 16384), false, encoding);
err = new PrintStream(new BufferedOutputStream(term.wrapOutIfNeeded(new FileOutputStream(FileDescriptor.err)), 16384), false, encoding);
ansi = true;
} else {
out = AnsiConsole.out;
err = AnsiConsole.err;
ansi = false;
}
//
FileInputStream in = new FileInputStream(FileDescriptor.in);
ConsoleReader reader = new ConsoleReader(null, in, out, term);
//
final JLineProcessor processor = new JLineProcessor(ansi, shell, reader, out);
//
InterruptHandler interruptHandler = new InterruptHandler(processor::interrupt);
interruptHandler.install();
//
Thread thread = new Thread(processor);
thread.setDaemon(true);
thread.start();
try {
processor.closed();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
剩下的就是像这样将其加载到上下文中:
@Configuration
@AutoConfigureAfter(CrshAutoConfiguration.class)
public static class ShellConfiguration {
@Bean
InteractiveShellRunner runner(@Qualifier("shellBootstrap") PluginLifeCycle crshBootstrapBean){
return new InteractiveShellRunner(crshBootstrapBean);
}
}
我想要 运行 一个 Spring 嵌入 CRaSH shell 的引导应用程序,但我想要 CRaSH shell 而不是通过 SSH/Telnet 访问] 在当前控制台(即 direct/standalone)中启动而无需任何密码,只要 Spring 完成所有 bean 的初始化。
当用户键入 exit
或按 Ctrl+D 时,应用程序应关闭。
另外,应该禁用 SSH 和 Telnet 支持。
PS。如果应用程序可以从 stdin 读取命令,例如
./crshapp < somefile.cmd
cat somefile.cmd | ./crshapp
我遇到了同样的问题,所以我实现了以下代码以附加到由引导配置的 运行 shell。
我通过复制 org.crsh.standalone.CRaSH 中的一些代码来做到这一点,这些代码加载了一个独立的 shell。
import org.crsh.console.jline.JLineProcessor;
import org.crsh.console.jline.Terminal;
import org.crsh.console.jline.TerminalFactory;
import org.crsh.console.jline.console.ConsoleReader;
import org.crsh.plugin.PluginLifeCycle;
import org.crsh.shell.Shell;
import org.crsh.shell.ShellFactory;
import org.crsh.util.InterruptHandler;
import org.fusesource.jansi.AnsiConsole;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.CommandLineRunner;
import java.io.*;
public class InteractiveShellRunner implements CommandLineRunner, InitializingBean, DisposableBean {
final private PluginLifeCycle crshBootstrapBean;
private Shell shell;
private Terminal term;
public InteractiveShellRunner(PluginLifeCycle crshBootstrapBean) {
this.crshBootstrapBean = crshBootstrapBean;
}
@Override
public void afterPropertiesSet() throws Exception {
ShellFactory shellFactory = crshBootstrapBean.getContext().getPlugin(ShellFactory.class);
shell = shellFactory.create(null);
}
@Override
public void destroy() throws Exception {
try {
if (term != null) {
term.restore();
}
} catch (Exception ignore) {
}
}
@Override
public void run(String... args) throws Exception {
if (shell != null) {
term = TerminalFactory.create();
//
String encoding = jline.internal.Configuration.getEncoding();
// Use AnsiConsole only if term doesnt support Ansi
PrintStream out;
PrintStream err;
boolean ansi;
if (term.isAnsiSupported()) {
out = new PrintStream(new BufferedOutputStream(term.wrapOutIfNeeded(new FileOutputStream(FileDescriptor.out)), 16384), false, encoding);
err = new PrintStream(new BufferedOutputStream(term.wrapOutIfNeeded(new FileOutputStream(FileDescriptor.err)), 16384), false, encoding);
ansi = true;
} else {
out = AnsiConsole.out;
err = AnsiConsole.err;
ansi = false;
}
//
FileInputStream in = new FileInputStream(FileDescriptor.in);
ConsoleReader reader = new ConsoleReader(null, in, out, term);
//
final JLineProcessor processor = new JLineProcessor(ansi, shell, reader, out);
//
InterruptHandler interruptHandler = new InterruptHandler(processor::interrupt);
interruptHandler.install();
//
Thread thread = new Thread(processor);
thread.setDaemon(true);
thread.start();
try {
processor.closed();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
}
剩下的就是像这样将其加载到上下文中:
@Configuration
@AutoConfigureAfter(CrshAutoConfiguration.class)
public static class ShellConfiguration {
@Bean
InteractiveShellRunner runner(@Qualifier("shellBootstrap") PluginLifeCycle crshBootstrapBean){
return new InteractiveShellRunner(crshBootstrapBean);
}
}