gwt Java ProcessBuilder如何获取实时输出
我有一个正在成功运行的ProcessBuilder,它在服务器上扫描DVB-T的频道广播,我希望输出到一个网页
服务器代码如下所示:
private static StringBuilder scan_output = null;
private static String scan_result = "";
@Override
public boolean scanByBroadcaster(String user, String broadcaster) {
UserAccountPermissions perm = validateUserEdit(user); // allowed to run scan?
if (perm == null) return false;
String[] commands = {
"/usr/bin/scan",
dvbDir + broadcaster,
"-o",
"zap",
"-U",
"-q",
"-a",
"5",
">",
LoginConstants.loc_dvb_scanfile
};
System.out.println("Scan by broadcast: " + broadcaster);
scan_output = new StringBuilder();
new ScanThread(commands).start();
return false;
}
// runs the scan independant and the IO capture
private static class ScanThread extends Thread {
String[] commands = null;
public ScanThread(String[] commands) {
this.commands = commands;
}
public void run() {
ProcessBuilder pb = new ProcessBuilder(commands);
Process process;
try {
System.out.println("Scan thread running");
process = pb.start();
IOScanOutputHandler handler = new IOScanOutputHandler(process.getInputStream());
handler.start();
process.waitFor();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
//scan_output = null;
System.out.println("Scan thread finished");
}
}
// background thread to capture output of scan (as it arrives)
// this only captures the final scan results though
private static class IOScanOutputHandler extends Thread {
private InputStream inputStream;
IOScanOutputHandler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
Scanner br = null;
try {
System.out.println("Scan thread IO capture running");
br = new Scanner(new InputStreamReader(inputStream));
String line = null;
while (br.hasNextLine()) {
line = br.nextLine();
scan_output.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
System.out.println("Scan thread IO capture finished");
scan_result = scan_output.toString();
scan_output = null;
}
}
// polled by web interface every second
@Override
public String pollScanResult(String user) {
if (validateUserEdit(user) == null) return null;
StringBuilder sb = scan_output; // grab instance
if (sb == null) return null;
return sb.toString();
}
我实际得到的最终输出是进入“LoginConstants.loc_dvb_scanfile”的内容,而不是此输出:
ERROR: invalid enum value '7378'
ERROR: invalid enum value '3300'
ERROR: invalid enum value '0'
ERROR: invalid enum value '8MHz'
ERROR: invalid enum value '2/3'
ERROR: invalid enum value 'NONE'
ERROR: invalid enum value 'QAM2'
>>> tune to: 706000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 778000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 2:INVERSION_AUTO:BANDWIDTH_AUTO:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO
__tune_to_transponder:1910: ERROR: Setting frontend parameters failed: 22 Invalid argument
>>> tune to: 2:INVERSION_AUTO:BANDWIDTH_AUTO:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO
__tune_to_transponder:1910: ERROR: Setting frontend parameters failed: 22 Invalid argument
>>> tune to: 770000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 698000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 746000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 762000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_16:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
WARNING: filter timeout pid 0x0011
WARNING: filter timeout pid 0x0000
WARNING: filter timeout pid 0x0010
通过RPC调用从GWT客户端开始扫描。为简洁起见,以下是代码:
private void runScanQuick() {
server.checkEditAccess(user, new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
log.info("runScanQuick server failure");
}
@Override
public void onSuccess(Boolean result) {
if (result == false) return; // not allowed to run scan
final DialogBox dia = new DialogBox();
final Frame frame = new Frame(url_base + url_ext_scanbybroadcaster);
frame.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
String broadcaster = scan_country.getSelectedItemText() + "-" + scan_broadcaster.getSelectedItemText();
log.info("Scan file: " + broadcaster);
Document doc = IFrameElement.as(frame.getElement()).getContentDocument();
doc.getElementById("broadcaster").appendChild(new HTML(broadcaster).getElement());
Button okay = Button.wrap(doc.getElementById("okay"));
Button cancel = Button.wrap(doc.getElementById("cancel"));
cancel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
dia.hide();
}
});
okay.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
dia.hide();
runScanQuickStart();
}
});
}
});
frame.setSize("500px", "500px");
dia.add(frame);
dia.setGlassEnabled(true);
dia.setStyleName("");
dia.center();
dia.show();
}
});
}
private void runScanQuickStart() {
final DialogBox dia = new DialogBox();
final Frame frame = new Frame(url_base + url_ext_scanbroadcasterprogress);
frame.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
Document doc = IFrameElement.as(frame.getElement()).getContentDocument();
String broadcaster = scan_country.getSelectedItemText() + "-" + scan_broadcaster.getSelectedItemText();
doc.getElementById("title").appendChild(new HTML(broadcaster).getElement());
Button okay = Button.wrap(doc.getElementById("okay"));
final TextArea area = TextArea.wrap(doc.getElementById("textarea"));
final Timer timer = new Timer() {
@Override
public void run() {
server.pollScanResult(user, new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
cancel();
}
@Override
public void onSuccess(String result) {
if (result == null) cancel();
else {
area.setText(result);
}
log.info("Polled for scan result");
}
});
}
};
okay.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
timer.cancel();
dia.hide();
}
});
server.scanByBroadcaster(user, broadcaster, new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
log.info("runScanQuickStart server call failed");
}
@Override
public void onSuccess(Boolean result) {
if (result == false) return;
timer.scheduleRepeating(1000);
}
});
}
});
frame.setSize("740px", "500px");
dia.add(frame);
dia.setGlassEnabled(true);
dia.setStyleName("");
dia.center();
dia.show();
}
除了我不知道如何从ProcessBuilder获取实时输出之外,一切都正常
有人知道如何获取实时输出,以便我可以在网页中显示实时反馈吗
我在想可能是stderr,stdout或其他什么
# 1 楼答案
经过两天的努力,我终于在半小时后找到了答案。Grr
我更改了这个以获取错误流:
在服务器函数scanByBroadcaster()中,我刚刚添加了return true,这使客户端计时器能够开始轮询
呸