I am trying to implement a feature to restart PostrgeSQL server from Java code using Runtime.getRuntime().exec() method. The method is working fine if the PostgreSQL server is not SSL enabled but if the PostreSQL server is SSL enabled and if the private key is encrypted with a password, it requires passphase to be passed. I tried with below code for implementing the same,
String postgreSQLRestartCMD =
"/u/postgreSQL/pg_ctl -D /u/postgreSQL/data restart -w";
//-w option waits until the passphase is sent
final Process restartPosgreSQLServer = Runtime.getRuntime().exec(postgreSQLRestartCMD);
PrintStream ps = new PrintStream(restartPosgreSQLServer.getOutputStream());
ps.println("keyPassword"); // sending passphasse here
new Thread(new Runnable() {
#Override
public void run() {
try {
IOUtils.copy(restartPosgreSQLServer.getInputStream(), logWriter);
}
catch (final IOException e) {
logWriter.println("Error occurred while reading InputStream.");
e.printStackTrace(logWriter);
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
try {
IOUtils.copy(restartPosgreSQLServer.getErrorStream(), logWriter);
}
catch (final IOException e) {
logWriter.println("Error occurred while reading ErrorStream.");
e.printStackTrace(logWriter);
}
}
}).start();
int returnStatus = restartPosgreSQLServer.waitFor();
if (returnStatus == 1) {
logWriter.println("Error has occured while running PostgreSQL server.");
} else {
logWriter.println("PostgreSQL has started successfully.");
}
But the server is not getting started. I am trying in Linux. In console its getting struck with below line and I guess passohase not sent properly.
Enter PEM pass phrase:
Where is this going wrong and why is the passphase not sent?
Edit
Upon digging further I just found that Runtime.getRuntime().exec(cmd) is creating new process, my ps.println("password") is passed to parent process. But I am not sure, whether my observation is right.
What you are not taking into account is that before programs ask for the password, they flush the input buffer. Otherwise it would be very easy to have extra characters read in for password, that the user accidentally typed before the password prompt.
You'll have to raise the level of complexity of your code to analyze the process's output and print to its stdin only after actually witnessing the password prompt.
Related
I'm wondering how to log information when a server has successfully started. I cannot do this as simple as that:
createServer().start(Exit.NEVER);
System.out.println("Server is running...");
because the instruction createServer().start(Exit.NEVER) doesn't return back. This is a call to external library that uses a method with a loop similar to while(true).
I cannot also run the server in a new thread and then log information about successful start because the server may throw exception and hence there was a failure.
public void start () {
new Thread("Server") {
#Override
public void run() {
try {
createServer().start(Exit.NEVER);
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
}
}.start();
System.out.println("Server is running...");
}
Last solution I can think of is to wait a couple of second after createServer().start(Exit.NEVER) and then log the successful start as there was no exception thrown. This is not a perfect solution as we can wait for example 5 seconds and the log the successful start but one second later the server may throw exception.
How do I then can tell whether the server has started successfully and hence log this information?
EDIT
The server I'm using is Takes https://github.com/yegor256/takes.
public void connect() {
final String msg = "";
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
s = new Socket("192.168.1.3", 1337);
textView.setText("Connection acquired");
out = s.getOutputStream();
output = new PrintWriter(out);
output.println(msg);
textView.setText("message sent : " + msg.length());
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
I am using the above code to connect to desired IP [192.168.1.3]... I have created another program at the other end... The problem is that the IP sometimes changes to 192.168.1.4 or 192.168.1.6... and when I use another network it changes to 192.168.43.2... now due to this I have to go every time into the code and change it manually....
Is there any function or any other thing that might search for IPs available then check if desired port exists and then connect... Thanks in advance
That's why DNS names exist. If you use an IP address, you have to use that exact address. If you use DNS, you do a name->IP lookup. Get a dynamic DNS provider and use that to give your server a name.
You really do not want to start port scanning to find open ports. You will be treated as an attacker and kicked off the network, because you really would be doing something attackers do.
I am not sure what is happening here. I am starting a RMI server in a separate JVM. While connecting to the instance calling the remote method, the method get stuck after a very short time. The execution continues as soon as I shutdown the client process.
What am I doing wrong?
class Client
...
//name some kind of name
String name= "HelloService";
//libname points to a runnable jar with the server class as main class
ProcessBuilder jvm= new ProcessBuilder(javaPath, "-jar", libname, "-n", name);
jvm.start();
//Waiting for RMI server to start
try { Thread.sleep(10000); } catch ...
try {
Registry registry= LocateRegistry.getRegistry(1199);
//String as input and String as output
IRemoteService<String, String> service= (IRemoteService<String, String>) registry.lookup(name)
String returnVal= service.execute("SomeValue");
return returnVal;
} catch ...
Following by the server code snip. The server code is packed in a runnable jar with itself as the MainClass.
class Server implements IRemoteService<String, String>
//Is not returning a value, due the fact that I liked to examine the behaviour of
//this method. Doing this by running an infinite loop.
public String execute(String str) {
log.info("Running doExectue from "+getClass().getSimpleName());
int i=0;
while(true) {
i++;
log.info(String.valueOf(i));
}
}
protected static void register(String name, IRemoteService service) {
try {
IRemoteService rsStub= (IRemoteService) UnicastRemoteObject.exportObject(service,0);
Registry registry= LocateRegistry.getRegistry(1199);
try {
registry.bind(name, rsStub);
} catch (ConnectException ce) {
registry= LocateRegistry.createRegistry(1199);
registry.bind(name, rsStub);
}
} catch ...
}
public static void main(String[] args) {
String rmiName= args[1];
IRemoteService<String, String> service= (IRemoteService<String, String>) new Server();
register(rmiName, service);
}
Now if I start the client the log file displayes 36 runs of the loop in method "execute". Than it stops. There is no other client getting this object or calling this method too.
It starts a again and is running forever as soon as I killed the Client process.
For me it looks like that the client is blocking the execution of the remote server methods. But I have no clue how to overcome this situation.
Thanks for any help in advance,
Danny
What you describe is impossible. The client can't block the server while the server is executing a remote method. Find another explanation.
thanks for your support. You are right a RMI client can't block the server. So I was really confused. But I found the failure.
It about the process is writing to the console. As soon as the buffer is full the process is stopping to wait for someone collecting the output.
After I removed the ConsoleAppender from the log configuration the job runs as expected.
On my machine, the following code compiles within Eclipse but throws an exception within Netbeans. The error message says "Exception in thread "main" java.net.BindException: Address already in use".
What is the proper configuration within Netbeans to make this code compile? It seems like the problem has to do with the fact that I have two main functions. If I start running either one of the apps, the second will fail to start, throwing the exception posted above.
Server.java
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
Server myServ = new Server();
myServ.run();
}
public void run() throws Exception {
ServerSocket mySS = new ServerSocket(9999);
Socket SS_accept = mySS.accept();
InputStreamReader mySR = new InputStreamReader(SS_accept.getInputStream());
BufferedReader myBR = new BufferedReader(mySR);
String temp = myBR.readLine();
System.out.println(temp);
}
}
Client.java
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
Client myCli = new Client();
myCli.run();
}
public void run() throws Exception {
Socket mySkt = new Socket("localhost", 9999);
PrintStream myPS = new PrintStream(mySkt.getOutputStream());
myPS.println("Hello server");
}
}
The problem is due to the fact that you left one instance of your server running and then started another one.
The way to achieve what I want is to right-click on the particular class (ex. Server.java) that I want to run and select "Run this file". This enables me to run only the Server app. Then, do the same process for the other file, Client.java.
However, Netbeans is somewhat confusing/deceiving in this particular circumstance. What Netbeans does is it runs the Server process, but labels that process as the name of the project (ex. MyTestNetworkingProject) and puts a run number on it, thus giving us MyTestNetworkingProject run #1 (it actually leaves out the #1 on the first process). Then, if I go to the Client.java file and select "Run this file", it generates a second process, MyTestNetworkingProject run #2. It then generates a second results window down at the bottom of the screen, as it generates these in new tabs as new processes get created.
Because of the nature of my specific code, what I wanted to see in my results window to confirm that my application was working was I wanted to observe the Server.java results window (which in this case is MyTestNetworkingProject run #1). Given my exact sequence of steps outlined above of running the different files, run #2 is the last run process and thus the tab on top, covering the run #1 tab. I can click on run #1 and see the results I was hoping to see in the console ("Hello server"), but I just have to know/remember that MyTestNetworkingProject run #1 represents the Server app and not the Client app.
Uncool, IMO.
If you write this in Windows OS,you can use "netstat -nao" to see which process use the 9999 port.If it is some unimportant process,you can kill this process.Otherwise you can change the port of the pragram.
I change the port address and it work for me in the Neat Beans IDE . This problem will come if we used the same port address for other one times . so to fix this error you have to change the port address and I am sure it will work
Server.java
public class SocServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5001);
Socket client = server.accept();
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeBytes("Hello Sockets\n");
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client.java
public class SocClient {
public static void main(String[] args) {
try {
Socket socClient = new Socket("localhost", 5001);
InputStream is = socClient.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String receivedData = br.readLine();
System.out.println("Received Data: " + receivedData);
} catch (IOException e) {
e.printStackTrace();
}
}
}
refer above code and it works for me..
I did try the method catch and solved the problem.
I want to stop a server running on port 8080. In my java application, whenever application is closed, also this server needs to be stopped. But I could not find any solution except stopping the server manually. Is there any way to stop a server with codes ? By the way, I am using Windows 7
How are you starting SymmetricDs? As a windows service, as a WAR or embedded in you application?
Looking at the user guide it seems that if you could embed it in your code you ought to be able to start and stop it directly. More details in the user guide along with the following example code.
import org.jumpmind.symmetric.SymmetricWebServer;
public class StartSymmetricEngine {
/**
* Start an engine that is configured by two properties files. One is
* packaged with the application and contains overridden properties that are
* specific to the application. The other is found in the application's
* working directory. It can be used to setup environment specific
* properties.
*/
public static void main(String[] args) throws Exception {
SymmetricWebServer node = new SymmetricWebServer(
"classpath://my-application.properties");
// this will create the database, sync triggers, start jobs running
node.start(8080);
// this will stop the node
node.stop();
}
}
try {
// Execute a command to terminate your server
String command = "command to stop your server";
Process child = Runtime.getRuntime().exec(command);
} catch (IOException e) {
}
Why don't you check Cargo? It provides a Java API to start/stop Java containers. You can find the list of supported containers in the home page.
Since i did not see the code , how are creating server and accepting connection ,below
i have given you the following ooptions.you should try to implement the firstway ,
rest of the option wont guarantee whether correct process will be killed.
public void stopServer()
{
threadReference.interrupt();
}
while(!Thread.interrupted())
{
// Accept Server Connection
try
{
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
Runtime.getRunTime().addShutDownHook(new Thread()
{
public void run()
{
try
{
ref.stop();
} catch (IOException e)
{
// close server socket
// other clean up
e.printStackTrace();
}
}
});
you need to specify this in Runtime.getRuntime() TASKKILL /F /IM or there is a jps which is better to kill relevant process.
try
{
Process p = Runtime.getRuntime().exec("TASKKILL /F /IM communicator*");
BufferedReader in =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String result = null;
while ((result= in.readLine()) != null) {
if ( "SUCCESS".equals(result.substring(0,7))
{
break;
}
}
} catch (IOException e)
{
e.printStackTrace();
}