简体   繁体   English

我可以从Java写入Beanshell控制台吗?

[英]Can I write to the Beanshell console from Java?

I'm using Beanshell as an embedded debugging tool in my app. 我在我的应用程序中使用Beanshell作为嵌入式调试工具。 It means I can telnet to my app and poke around with its internals while it is running (I typically wrap the telnet session with rlwrap). 这意味着我可以远程登录到我的应用程序并在其运行时使用其内部功能(我通常用rlwrap包装telnet会话)。

The problem is that the only way I've found to print to the Beanshell console, rather than stdout of the application itself, is the print() method within Beanshell. 问题是,我发现打印到Beanshell控制台的唯一方法是Beanshell中的print()方法,而不是应用程序本身的stdout。

But I'd like to write code in Java that I can call from Beanshell, which will output to the Beanshell console - ie. 但我想用Java编写代码,我可以从Beanshell调用它,它将输出到Beanshell控制台 - 即。 it will be shown in my telnet session, not sent to stdout of the application, as happens if you try to use System.out or System.err. 它将显示在我的telnet会话中,而不是发送到应用程序的stdout,如果您尝试使用System.out或System.err。

Is this possible? 这可能吗?


edit: To further clarify, I'm setting up a Beanshell server as follows: 编辑:为了进一步说明,我正在设置一个Beanshell服务器,如下所示:

public static void setUpBeanshell() {
    try {
        i.setShowResults(true);
        i.eval(new InputStreamReader(Bsh.class.getResourceAsStream("init.bsh")));
        i.eval("server(" + Main.globalConfig.beanShellPort + ");");
    } catch (final EvalError e) {
        Main.log.error("Error generated while starting BeanShell server", e);
    }
}

How would I modify this such that I can write a Java function that outputs to the telnet session (rather than to System.out of my application) 我如何修改它,以便我可以编写一个输出到telnet会话的Java函数(而不是我的应用程序的System.out)

I'll copy it there as it seems that comments are disregarded this days. 我会把它复制到那里,因为这些日子里的评论似乎被忽视了。

you can: instead of having a method which print debug information to the standard output returns that debug information: 你可以:而不是有一个方法将调试信息打印到标准输出返回调试信息:

class ClientList {
 Integer clients = 0;
 public String debugClientList() {
   return clients.toString();
 }

and then calling it from beanshell 然后从beanshell调用它

print(clients.debugCientList());

will give you an output on your telnet 会在你的telnet上给你一个输出

or if you need it more logger like, you need to interact with the Interpreter object directly 或者如果你需要更多的记录器,你需要直接与Interpreter对象进行交互

InterpreterSingleton {  
    public static final void Console console = new Interpreter();
}
....

class ClientList {
 Integer clients = 0;
 public void addClient(Client c) {
    ....
    InterpreterSingleton.console.print("Client added, clients now are " + clients);
 }

I'm replying there to the comment as it will need some more coding; 我在那里回复评论,因为它需要更多的编码; the telnet implementation uses a different interpreter for each connection, so you have to expose that interpreter to the objects for printing to the telnet client. telnet实现为每个连接使用不同的解释器,因此您必须将该解释器公开给对象以便打印到telnet客户端。 The quickest way is to change some bit in the default telnet server and use the modified one to start your server, instead of using the server() scripted command (it's under lgpl or sun license terms) 最快的方法是在默认的telnet服务器中更改一些位并使用修改后的服务器启动服务器,而不是使用server()脚本命令(它在lgpl或sun许可条款下)

note that this way have an interpreter started for each connection; 请注意,这种方式为每个连接启动了一个解释器; the easy and quick fix is to maintain a list of all the running interpreters and print to each one the debugging information, so: 简单快速的解决方法是维护所有正在运行的解释器的列表,并向每个解释器打印调试信息,因此:

class InterpreterSingletonList {  
    public static final void Set<Interpreter> is = new HashSet();
    void printToAll(String s) {
         for (Interpreter i: is) {
             i.print(s);
         }
    }
}



package bsh.util;

import java.io.*;

import java.net.Socket;
import java.net.ServerSocket;
import bsh.*;

/**
    BeanShell remote session server.
    Starts instances of bsh for client connections.
    Note: the sessiond effectively maps all connections to the same interpreter
    (shared namespace).
*/
public class Sessiond extends Thread
{
    private ServerSocket ss;
    NameSpace globalNameSpace;

    public Sessiond(NameSpace globalNameSpace, int port) throws IOException
    {
        ss = new ServerSocket(port);
        this.globalNameSpace = globalNameSpace;
    }

    public void run()
    {
        try
        {
            while(true)
                new SessiondConnection(globalNameSpace, ss.accept()).start();
        }
        catch(IOException e) { System.out.println(e); }
    }
}

class SessiondConnection extends Thread
{
    NameSpace globalNameSpace;
    Socket client;

    SessiondConnection(NameSpace globalNameSpace, Socket client)
    {
        this.client = client;
        this.globalNameSpace = globalNameSpace;
    }

    public void run()
    {
        try
        {
            InputStream in = client.getInputStream();
            PrintStream out = new PrintStream(client.getOutputStream());
            /* this is the one you're looking for */
                        Interpreter i = new Interpreter( 
                new InputStreamReader(in), out, out, true, globalNameSpace);
            i.setExitOnEOF( false ); // don't exit interp
                    /*store the interpreter on the list*/
                    InterpreterSingletonList.is.add(i);
            i.run();
                    /*remove it (i.run() blocks)*/
                    InterpreterSingletonList.is.remove(i);
        }
        catch(IOException e) { System.out.println(e); }
    }
}

I think it's not possible with out hack..., sorry, adapting the telnet server implementation of BSH. 我认为这是不可能的黑客...,抱歉,适应BSH的telnet服务器实现。

The class we're looking at is bsh.util.Sessiond . 我们bsh.util.Sessiond的类是bsh.util.Sessiond Once started, it opens and maintains a telnet server. 一旦启动,它将打开并维护一个telnet服务器。 When ever it receives a command, it creates a new worker thread, this on creates a new bsh.Interpreter with the correct input and output streams (derived from the socket) and runs the interpreter. 当它收到命令时,它会创建一个新的工作线程,这将创建一个新的bsh.Interpreter,其中包含正确的输入和输出流(从套接字派生)并运行解释器。

So it makes sense, that only output of interpreted commands is send to the telnet client, because System.out and System.err are not redirected. 所以有意义的是,只有解释命令的输出才会发送到telnet客户端,因为System.outSystem.err不会被重定向。

But that exactly is what has to be done in your case: redirect System.out and System.err to the sockets output stream before the interpreter runs the command and reset the streams after completion. 但这正是您需要做的事情:在解释器运行命令之前将System.outSystem.err重定向到套接字输出流,并在完成后重置流。

I'd suggest, you copy the bsh.util.Sessiond class to something like mybsh.util.DebuggerSessiond , apply the redirection code to the run method of the inner class SessiondConnection and modify bsh/commands/server.bsh to start this 'new' telnet server in addition (or instead of the original one). 我建议你将bsh.util.Sessiond类复制到类似mybsh.util.DebuggerSessiond东西,将重定向代码应用到内部类SessiondConnection的run方法,并修改bsh/commands/server.bsh以启动这个'new 'telnet服务器另外(或代替原来的)。 (I guess, this script starts the servers...) (我想,这个脚本启动了服务器...)

Source code can be found here: beanshell repository 源代码可以在这里找到: beanshell存储库

If all your application's output is written using some logging framework anyways, you could write a custom appender/handler which besides logging to say a file would write to the beanshell console in addition? 如果所有应用程序的输出都是使用某些日志记录框架编写的,那么您可以编写一个自定义appender / handler,除了日志记录之外还要写一个文件会写入beanshell控制台吗? Possibly enabling and disabling the console-logging after executing some beanshell command. 执行某些beanshell命令后,可能启用和禁用控制台日志记录。

(I wasn't aware of beanshell before, but it seems useful!) (我以前不知道豆壳,但它看起来很有用!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否有一个Java数据库API,可以从beanshell中单独使用? - Is there a Java database API which I can use exclusively from beanshell? 是否可以将参数传递给源自另一个Beanshell脚本的外部Beanshell脚本? - Can I pass arguments to a external Beanshell script, sourced from another Beanshell script? beanshell采样器,我想从jmeter访问Java代码 - beanshell sampler, i want access java code from jmeter 我如何编写 AverageSum.java 不同的控制台输入? - How I can write AverageSum.java different console inputs? 如何编写sails beanshell java 脚本来读取文件名以“SampleFile***.csv”开头的最新文件 - How do I write a sailpoint beanshell java script to read a latest file whose filename starts with ‘SampleFile***.csv’ 有没有 BeanShell 的替代品? 类似于 javascript 或 groovy 控制台的 Java 控制台? - Is there an alternative to BeanShell ? Something like javascript or groovy console for Java? 使用来自beanshell或Java程序的ANTLR - Using ANTLR from beanshell or Java program 在 TestNG xml 文件中,如何在 beanshell 中调用另一个 java 方法? - In TestNG xml file, How can I call another java method inside beanshell? 如何在Java中写入控制台? - How do I write to the console in java? 如何从 java 代码输出到 Jenkins 控制台? - How can I output from java code to the Jenkins console?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM