我正在使用Primefaces的终端组件和JSch以ssh方式连接到远程桌面。对于exec通道,由于会话和通道在每个命令时都关闭,执行需要花费太多时间,我没有设法利用这一点。所以我将通道改为shell,现在我尝试“重定向”标准输入/输出蒸汽。我的代码是这样的:
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@ManagedBean
@SessionScoped
public class TerminalController implements Serializable{
public TerminalController(){
jsch=new JSch();
InputStream in=null;
PrintStream out=System.out;
try{
session=jsch.getSession(user, ip, port);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(passwd);
session.connect();
channel=session.openChannel("shell");
channel.setInputStream(in);
channel.setOutputStream(out);
channel.connect();
}catch(Exception ee){
System.out.println(ee);
} }
public String handleCommand(String command, String[] params) {
command=command+StringUtils.join(params," ");
in=IOUtils.toInputStream(command);
String result=out.toString();
out.flush();
return result;}
我知道这很糟糕,我还是java的初学者。我考虑的另一个问题是,在从iostream到string的转换过程中,我可能会丢失enter按钮函数!我在等待你的建议、解决方案和建议。
在变量中设置对通道没有影响,调用
out.toString()
不会得到任何结果。
您需要将命令(及其参数)写入通道,然后从那里读取输出。此外,不要使用
setInputStream
或setOutputStream
方法(如果您有要读取或写入的现有流,它们是好的,而您没有)。
public class TerminalController implements Serializable{
BufferedReader fromChannel;
PrintWriter toChannel;
Channel channel;
Session session;
public TerminalController(){
jsch=new JSch();
try {
session=jsch.getSession(user, ip, port);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(passwd);
session.connect();
channel = session.openChannel("shell");
InputStream inStream = channel.getInputStream();
fromChannel = new BufferedReader(new InputStreamReader(inStream, "UTF-8"));
OutputStream outStream = channel.getOutputStream();
toChannel = new PrintWriter(new OutputStreamWriter(outStream, "UTF-8"));
channel.connect();
} catch(Exception ee) {
ee.printStackTrace();
}
}
public String handleCommand(String command, String[] params) {
command = command + StringUtils.join(params," ");
toChannel.println(command);
StringBuilder result = new StringBuilder();
while(true) {
String line = fromChannel.readLine();
result.append(line);
if(looksLikePrompt(line))
return result.toString();
result.append("\n");
}
}
}
困难的部分实际上是知道远程命令的输出何时完成,您需要返回(这是在
looksLikePrompt
方法中,我不知道如何编写)。
我不确定Primeface终端组件的
CommandHandler
原则是否是创建交互终端的正确设计,在交互终端中,终端不需要知道命令何时完成。当命令需要更多输入时会发生什么?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.apache.commons.lang.StringUtils;
import org.fusesource.jansi.AnsiConsole;
import org.fusesource.jansi.AnsiString;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
@ManagedBean
@SessionScoped
public class TerminalController {
BufferedReader fromChannel;
PrintWriter toChannel;
Channel channel;
Session session;
JSch jsch;
public TerminalController() {
jsch = new JSch();
try {
session = jsch.getSession("leoks", "localhost", 22);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword("xxx");
session.connect(Integer.MAX_VALUE); // 3 secs timeout
channel = session.openChannel("shell");
InputStream inStream = channel.getInputStream();
fromChannel = new BufferedReader(new InputStreamReader(inStream,
"UTF-8"));
OutputStream outStream = channel.getOutputStream();
toChannel = new PrintWriter(new OutputStreamWriter(outStream,
"UTF-8"));
channel.connect();
StringBuilder result = new StringBuilder();
boolean stop = false;
while (!stop) {
// prompt does not end with newline...
char c = (char) fromChannel.read();
result.append(c);
System.out.print(c);
if (result.toString().endsWith("$")) {
System.out.print("<<<");
stop = true;
}
}
} catch (Exception ee) {
ee.printStackTrace();
}
}
public String handleCommand(String command, String[] params)
throws IOException {
command = command + " " + StringUtils.join(params, " ");
toChannel.println(command);
toChannel.flush();
StringBuilder result = new StringBuilder();
AnsiConsole.systemInstall();
while (true) {
char c = (char) fromChannel.read();
result.append(c);
if (c == '$') {
AnsiString as = new AnsiString(result.toString());
String s = as.getPlain().toString();
s = s.replaceAll("\n", "<br>");
AnsiConsole.systemUninstall();
return s;
}
}
}
}
Jansi还有一个HTML呈现类,需要做一些工作才能正确地用BR替换\n,因为终端组件呈现HTML并静默地忽略所有格式错误的控制代码字符串。您可能还希望使用固定宽度字体替换终端CSS定义,例如,使用CSS,如
.ui-widget
{
font-family: "Courier New", Courier, monospace;
font-size: 0.8em;
}
和
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Terminal POC</title>
</h:head>
<h:body>
<h:outputStylesheet library="css" name="styles.css" />
<h:form>
<p:terminal
commandHandler="#{terminalController.handleCommand}"
height="300px"
welcomeMessage="Welcome..."
prompt=">" />
</h:form>
</h:body>
</html>
我试图将Spring Boot日志重定向到log4j2,但我看不出配置中缺少什么。 请注意,在A和B之间,在下面的图片1中,状态日志如何包含我想要的模式中的一些日志条目,但有些不包含。 图片中的“MYCONFIG” 我所追求的是在Spring Boot启动后自定义日志的格式。 图1-控制台输出: 图2-log4j2。属性文件 到目前为止,我所看到的是:https://logging.apache.
我一直在寻找完美的301重定向。但我发现了这么多的解决方案,不知道什么是最好的。 这是我想做的 http://domain.tld/ → https://domain.tld/ http://www.domain.tld/ → https://domain.tld/ https://www.domain.tld/ → https://domain.tld/ 最佳实践。 这是我喜欢的代码。至少现在是
问题内容: 是否可以在Python中临时重定向stdout / stderr(即在方法期间)? 编辑: 当前解决方案的问题(我最初记得但后来忘记了)是它们没有 重定向 ;相反,它们只是完全替换了流。因此,如果某个方法由于某种原因(例如,由于将流作为参数传递给某物)而具有该变量的 本地 副本,则该方法将无效。 有什么办法吗? 问题答案: 要解决某些函数可能已将流作为局部变量缓存的问题,因此替换全局变
问题内容: 在bash中,调用将在stdout上显示该命令的任何输出。 调用会将该命令的任何输出重定向到指定的文件(在本例中为“输出”)。 有没有一种方法可以将输出重定向到文件 并 在stdout上显示? 问题答案: 您想要的命令名为 : 例如,如果您只关心标准输出: 如果要包括stderr,请执行以下操作: 将通道2(stderr /标准错误)重定向到通道1(stdout /标准输出),以便将两
问题内容: 我正在尝试从主机系统调用docker的mysqldump,以从golang保存mysql dump。它可以与主机mysqldump正常工作,但不能与docker的mysqldump一起工作。 } 我只有非空数据库的 空mysql dump 问题答案: 解决方案是: } 没有“> dbname.sql”
问题内容: 我的基本程序从脚本GUI.py导入了它的GUI界面。 在我的GUI.py中: 但是它的作用是打开两个窗口,第一个窗口 (顶层 窗口 ) 按预期工作,第二个窗口 处于空闲状态 , 这是期望的,直到我单击某个按钮 ,该 按钮 在连续按下后打印数据,并且打印的数据应出现在第二个窗口的文本小部件中, 但是 不会发生,程序也没有响应,当我关闭“顶层”窗口时,会出现错误消息 “ TclError: