Hi I'm about to write a programm which starts multiple minecraft servers:
If you type 'start servername', it starts this server.
If you type 'watch servername', the program shows the output of this server and you should be able to send commands (to this server) at the same time until you type sth. like 'exit'. The problem is that I don't know how to refresh the outputscreen and take the inputs from the keyboard at the same time.
Here is my code from the server class:
class Server{
private String name;
private StartCommand command;
private boolean on = false;
private Process p = null;
public Server(StartCommand c, String name){
this.command = c;
this.name = name;
}
public void start(){
try {
p = Runtime.getRuntime().exec(command.getCommand());
System.out.println("Server: " + name + " is on now!");
on = true;
} catch (IOException e) {
e.printStackTrace();
on = false;
}
}
public void watch(){
try{
Scanner sc = new Scanner(System.in);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
on = false;
}
}
}
I hope you can help me.
Greetings,
Fabian
Server console should be displayed in separate terminal and client console where user can type in the command.
Similar to any server like mysql has a log where server output's are displayed. mysql client command where user type in their sql commands.
Or else redirect watch output to a file and then type the next command.
Related
Hey all not sure if there is a solution to my situation but here goes.
I am sending some 9 cmd.exe commands:
static String startDaemon_2 = "scm daemon start"; //Start Daemon
static String isRQRunning_3 = "RQAdapter.bat status"; //Check if RQ is running
static String startRQ_4 = "RQAdapter.bat start"; //Start RQ
...etc etc....
And this is my main code to fire off the commands:
static ProcessBuilder processBuilder = new ProcessBuilder();
static Process process = null;
static BufferedReader reader = null;
public static Object steps(String cmds, String dir_) {
processBuilder.command("cmd.exe", "/c", cmds);
processBuilder.directory(new File(dir_));
try {
process = processBuilder.start();
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.println(line);
if (line.contains("Key:")) {
return true;
} else if (line.contains("successfully")) {
return true;
} else if (line.contains("background")) {
return true;
} else if (line.contains("not")) {
//Load the adapter then
return "startRQM_4";
} else if (line.contains("sandbox")) {
return true;
} else if (line.contains("Misfit")) {
return true;
// repair goes here
} else if (line.contains("Unresolved")) {
//at this point theres no need to carry on. theres a conflick
return "fix";
}
}
int exitCode = process.waitFor();
System.out.println(line);
if (exitCode == 0) {
return true;
} else {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
And I call that function this way:
result = steps(startDaemon_2, scmDir);
if (result == "false") { System.out.println("not true"); }
result = steps(isRQMRunning_3, scmDir);
etc..... etc......
When I fire these same commands off in an actual cmd window it works just fine. Does what it should do. However, when the java program does the exact same thing it seems not to work even though there are no error.
Then I started thinking that maybe I need to define ProcessBuilder, process, reader
But it seems to still not work and without errors.
Is there some other type of way to do a few cmd.exe in the same setting? Seems it's just doing new stuff for each command.
What I mean by the last sentence is that I log in using the first command and then it goes to the other one which is start daemon, etc. But it seems to act like its brand new for each call (a.k.a. Isn't not logged in when firing the 2nd command, etc...)
With the code below, I'm trying to simulate the command shell, I even created a command and called it (Showerrlog) to help the user seeing his invalid commands that he entered during his current work session, as you can see, I did that using filehandler, which will save the wrong commands in a log file. But as you know filehandler will start a new file for each new working session, and the new file will be named as (file.log, file.log.1, file.log.2, etc) and so on, the question is: how to make the program to avoid opening a new file everytime, in other words isn't there any other way that the program will just format the previous work session and add the new one instead?
Or at least how to make the program open the last log file which belongs to the current work session ?
public class WithEyul implements Runnable {
String command;
public WithEyul(String command) {
this.command = command;
}
#Override
public void run() {
List<String> input = new ArrayList<String>();
StringTokenizer tokenizer = new StringTokenizer(command);
while (tokenizer.hasMoreTokens()) {
input.add(tokenizer.nextToken());
}
ProcessBuilder pb = new ProcessBuilder(input);
// ProcessBuilder creates a process corresponding to the input command
// now start the process
BufferedReader br = null;
try {
Process proc = pb.start();
// obtain the input and output streams
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
// read what the process returned
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} catch (java.io.IOException ioe) {
try {
System.err.println("Error");
Logger logger = Logger.getLogger("Testing");
FileHandler fh = new FileHandler("E:/MyLogFile.log");
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
logger.info(command);
} catch (SecurityException e) {
printStackTrace();
} catch (IOException ex) {
Logger.getLogger(WithEyul.class.getName()).log(Level.SEVERE, null, ex);
}
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ex) {
Logger.getLogger(WithEyul.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
and here is the main method class
public class TestProcessBuilder {
static void createProcess(String command) throws java.io.IOException {
Thread t = new Thread(new WithEyul(command));
t.start();
}
public static void main(String[] args) throws java.io.IOException {
String commandLine;
File wd;
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
System.out.println("\n\n***** Welcome to the Java Command Shell *****");
System.out.println("If you want to exit the shell, type END and press RETURN.\n");
// we break out with ‘END’
while (true) {
// show the Java shell prompt and read what command they entered
System.out.print("jsh>");
commandLine = console.readLine();
// if user entered a return, just loop again
if (commandLine.equals("")) {
continue;
}
if (commandLine.equalsIgnoreCase("Showerrlog")) {
try {
// Runtime.getRuntime().exec("E:\\MyLogFile.log");
if (Desktop.isDesktopSupported()) {
Desktop.getDesktop().open(new File("E:\\MyLogFile.log"));
}
} catch (IOException ex) {
Logger.getLogger(WithEyul.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (commandLine.toLowerCase().equals("end")) { //User wants to end shell
System.out.println("\n***** Command Shell Terminated. See you next time. BYE for now. *****\n");
System.exit(0);
}
createProcess(commandLine);
}
}
}
You could use the FileHandler constructor that allows you to specify the rotation, limit, and append options.
new FileHandler("E:/MyLogFile.log", 0, 1, true);
The FileHandler can rotate for a number of reasons that are out of your control. If you don't want to deal with file rotation you could open a FileOutputStream and wrap that with a StreamHandler. However, you will have to handle file locking conflicts.
You should also avoid creating and adding a handler that points to the same target file everytime an error is generated. You should install the handler on startup and store a string reference to your logger.
I'm trying to make a networking application, for a proof of concept project.
I need to keep the connection open, the joined clients, but the while loop I'm running never gets out of the first loop.
Code:
public class comm implements Runnable {
private Socket socket;
private String line, input;
boolean sending = true;
boolean connected = false;
private int me;
private BufferedReader br;
private PrintWriter pw;
doComms(Socket server) {
socket = server;
me = Main.connected;
}
public void run() {
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(socket.getOutputStream(), true);
while (true) {
System.out.println("Waiting");
readCommand();
}
} catch (Exception ex) {
System.out.println(ex);
}
}
private void readCommand() throws Exception {
String str;
while (br.readLine() != null) {
if (!connected) {
pw.println("connect");
}
str = br.readLine();
System.out.println(str);
if (str.startsWith("!START!")) {
System.out.println("User connected");
connected = true;
String[] split = str.split("#");
Main.jTable1.getModel().setValueAt(split[1], me, 2);
Main.jTable1.getModel().setValueAt(split[2], me, 3);
Main.jTable1.getModel().setValueAt("Connected...", me, 4);
}
}
}
}
Starting that code is fine, all it does is makes a new thread for each connected users, and the client software runs fine too. what am I doing wrong?
My best guess. It never gets out of the first readCommand call because readCommand itself is in an infinite loop:
while (br.readLine() != null) {
br.readLine will block until the next line from the socket input arrives. So the only way for the loop to exit is for the remote client to disconnect.
But the while loop I'm running never gets out of the first loop.
The first loop you are referring to is:
while(true) { ... }
This will never exit because true is always true.
I am fairly raw. I am trying to write a Java class to interact with Telnet. I saw that Apache Commons and Jsacpe had APIs. I am using Jscape's Sinetfactory. The Telnet I am connecting to sends a prompt to enter 'User name?:' as soon as telnet.connect() occurs. I am required to verify that this prompt is actually happening so I do not just write the answer when something else may happen. I am inexperienced with this and am sure there is a simple answer, just wondering if anyone might be able to help.
Here is what I have, its a bit sloppy because I've been playing around for awhile not sure how to actually read the last characters from the stream.
import com.jscape.inet.telnet.*;
public class TelnetTest extends TelnetAdapter {
private final static String USER = "xxx\r";
private final static String PWORD = "yyy\r";
private final static String COMMAND = "zzz\r";
private final static byte[] USER_BYTE = USER.getBytes();
private final static byte[] PWORD_BYTE = PWORD.getBytes();
private final static byte[] COMMAND_BYTE = COMMAND.getBytes();
private Telnet telnet = null;
private OutputStream output = null;
private static BufferedReader reader = null;
private boolean connected = false;
private String hostname = "qqq";
//TelnetInputStream tis = null; NOT IN USE AS OF NOW
public TelnetTest() throws IOException, TelnetException {
// create new Telnet instance
telnet = new Telnet(hostname);
// register this class as TelnetListener
telnet.addTelnetListener(this);
// establish Telnet connection
telnet.connect();
connected = true;
output = telnet.getOutputStream();
// HERE IS WHERE I NEED HELP, NOT SURE HOW TO CHECK STREAM
String str = null;
if ((str = reader.readline()).equals("User name?:")) {
telnet.getOutputStream().write(USER_BYTE);
}
// SAME CHECK WOULD HAPPEN HERE FOR "Password"
telnet.getOutputStream().write(PWORD_BYTE);
// ANOTHER SIMILAR CHECK HERE
telnet.getOutputStream().write(COMMAND_BYTE);
// sends all data entered at console to Telnet server
String input = null;
while ((input = reader.readLine()) != null) {
if (connected) {
((TelnetOutputStream) output).println(input);
} else {
break;
}
}
}
public boolean streamContainsString(Reader reader, String searchString)
throws IOException {
Scanner streamScanner = new Scanner(reader);
if (streamScanner.findWithinHorizon(searchString, 0) != null) {
return true;
} else {
return false;
}
}
// Invoked when Telnet socked is connected.
public void connected(TelnetConnectedEvent event) {
System.out.println("Connected");
}
// Invoked when Telnet socket is disconnected. Disconnect can
public void disconnected(TelnetDisconnectedEvent event) {
connected = false;
System.out.print("Disconnected. Press enter key to quit.");
}
// Invoked when Telnet server requests that the Telnet client begin performing specified TelnetOption.
public void doOption(DoOptionEvent event) {
// refuse any options requested by Telnet server
telnet.sendWontOption(event.getOption());
}
// Invoked when Telnet server offers to begin performing specified TelnetOption.
public void willOption(WillOptionEvent event) {
// refuse any options offered by Telnet server
telnet.sendDontOption(event.getOption());
}
// Invoked when data is received from Telnet server.
public void dataReceived(TelnetDataReceivedEvent event) {
// print data recevied from Telnet server to console
System.out.print(event.getData());
}
public Telnet getTelnet() {
return telnet;
}
// starts console program
public static void main(String[] args) {
try {
// create BufferedReader to read data from console
reader = new BufferedReader(new InputStreamReader(System.in));
// create new TelnetExample instance
TelnetTest example = new TelnetTest();
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
}
If you are reading/writing Strings then you should always use Reader and Writer. BufferedReader allows you to do line operations. So a BufferedReader wrapped around an Reader (around a InputStreamReader) will allow you to do a readLine() call to get the line of input from the connection:
BufferedReader reader =
new BufferedReader(new InputStreamReader(telnet.getInputStream()));
To write to the connection you would use a Writer around a OutputStreamWriter:
Writer writer = new OutputStreamWriter(telnet.getOutputStream()));
I'm not sure if that works with the stream from Telnet but it works with a raw Socket. You then could do something like the following pseudo code:
while (true) {
read a line from the server
some sort of if/then/else to test for the output
write your username/password or whatever is appropriate for the connection
repeat until some logout or IOException...
}
The Apache Telnet class has a number of interesting listeners and other handlers which you could use if you wanted to but the learning curve may be more. Here's a good sample application using TelnetClient:
http://www.java2s.com/Code/Java/Network-Protocol/ExampleofuseofTelnetClient.htm
I have already created simple instant messaging application in Java using Sockets and Swing. Right now it's communicating by resolving the hostname (PC name) or IP that's passes as a parameter. But is there a way to make it send a message with the Windows user ID (i.e. the user ID you use when you logon to Windows) as the parameter? This seems be easily done in C#, but how do I do it in Java?
Getting the username can be done using System.getProperty:
String name = System.getProperty("user.name");
This seems be easily done in C#
A 3rd party app (Winsent's Sent utility - winsentmessenger.com/sent) apparently can do this.
http://www.winsentmessenger.com/netsend/
The application in question is simply a wrapper around net send.
You could do the same, and invoke the process directly.
A solution lifted from:
http://members.iinet.net.au/~alw1746/awhome/freeware/WinPopup_java.txt
/*
WinPopup: send message to PC(s) on a Windows network from a Java program (like winpopup or net send).
Usage:
java WinPopup "user1,user2,..." "message"
eg. java WinPopup "peter" "where are you?" or java WinPopup 192.168.14.20 "Hello"
Build:
javac WinPopup.java
Alex Wong, Feb 2001
*/
import java.util.*;
import java.text.*;
import java.io.*;
public class WinPopup {
public static void main(String args[]) throws Exception {
String status;
if (args.length < 2) {
System.out.println("Usage: java WinPopup \"user1,user2,...\" \"msg\"");
System.exit(1);
}
if (args[0].length() < 1) {
System.out.println("User not found");
System.exit(1);
}
if (args[1].length() < 1) {
System.out.println("Message not found");
System.exit(1);
}
WinPopup popup=new WinPopup();
status=popup.alert(args[0],args[1]);
if (!status.equals("OK"))
System.out.println(status);
}
public String alert(String users,String msg) {
//loop thru list of users and net send the msg.
String buf,userList,user;
StringBuffer popup;
int ulen;
try {
if (users.length() < 1)
throw new Exception("User list not found.");
if (msg.length() < 1)
throw new Exception("Message not found.");
popup=new StringBuffer();
StringTokenizer st=new StringTokenizer(users,",");
while (st.hasMoreTokens()) {
buf=st.nextToken();
popup.append(buf).append(",");
}
if (popup.length() > 0) {
popup=popup.deleteCharAt(popup.length()-1);
userList=popup.toString();
ulen=userList.length();
for (int start=0,fin=0; fin <= ulen; fin++) {
if ((fin==ulen && fin > start) || userList.charAt(fin)==',') {
user=userList.substring(start,fin);
dosCmd("net send "+user+" \""+msg+"\"");
fin++;
start=fin;
}
}
}
return "OK";
}
catch (Exception e) {
return e.toString();
}
}
public void dosCmd(String cmd) {
//spawns a DOS process to run the net send command.
java.lang.Runtime rt;
Process proc;
try {
rt=java.lang.Runtime.getRuntime();
proc=rt.exec("c:\\winnt\\system32\\cmd.exe /C "+cmd);
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
errorGobbler.start();
outputGobbler.start();
int exitVal=proc.waitFor();
}
catch (Exception e1) {
System.out.println("dosCmd exception.");
System.out.println(e1.toString());
}
}
class StreamGobbler extends Thread {
//eat all stderr and stdout output.
InputStream is;
String type;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
;
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}