I am creating a server/client application, where the client can send system commands.
// Server Side
// command can be *nix/Windows system commands
public void run() {
while(true) {
try {
Runtime.getRuntime().exec(command);
} catch (Exception e) {e.printStackTrace();}
}
}
command is sent from client, and by executing it, in console it wont execute the command but just print it. So if command = "echo Hello", output in console(server side) will be echo Hello instead of just Hello.
Which method should I use to execute system command ?
cmd /C echo hello
echo is not a known/normal Windows executables but a cmd.exe input command.
One way to do this could be dump the client sent commands to a temp file (assuming) Linux like /tmp/some_cmds.sh and use bash to execute it e.g./usr/bin/sh /tmp/some_cmds.sh. Then use java ProcessBuilder API to execute the shell with argument as temp file. You can redirect the stdout and stderr to appropriate files and then send it back to the client as command output.
NOTE: This method is not portable across OS and it is dangerous too as hackers can potentially run arbitrary cmds from the client on your server.
Related
I had a Java program running a shell script with a Process, but for some reason when I try to run it it throws an error open terminal failed: missing or unsuitable terminal: unknown. From other SO questions, I think this is a tmux problem, but I'm not really sure how to solve it. Here's the code calling the script:
ProcessBuilder pb = new ProcessBuilder("/Users/user/eclipse-workspace/project/start.sh");
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
System.out.println("output: ");
String s;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
And here's the shell script:
#! /bin/sh
ssh -tt -i ~/.ssh/ssh-key.key opc#___._.___.___ tmux attach -d << END
./run.sh
END
exit 0
I have tried running the script from terminal, and it works from the terminal but it doesn't work when I run the Java program.
The problem is that you are attaching to an interactive tmux session, where you need to have a terminal which supports cursor movement codes etc.
The easy workaround is to not attach; just submit the command you want to run into the session.
ssh -tt -i ~/.ssh/ssh-key.key opc#___._.___.___ tmux send-keys './run' C-m
This obviously requires that whatever is running inside the remote tmux session is in a state where you can submit a shell command, i.e. at a shell prompt or similar. For robustness you might want to take additional measures to make sure this is always the case, or refactor your solution to avoid running inside tmux e.g. by having the command redirect its output to a file where you can examine it from any terminal at any time (though this assumes you don't also need to interact with it subsequently).
i have a Java program which executes the following shell script to restart it self.
sleep 5
nohup java -jar /home/my-dir/MyJar.jar &
If i run the script from a terminal, it just works as expected. However if the Java Program executes the script, the program starts normally but nothing gets written to the output file.
I start the script via the following code
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("/bin/sh", "/home/my-dir/start.sh");
try {
processBuilder.start();
logger.info("Successfully started");
} catch (IOException e) {
e.printStackTrace();
}
Following command worked for me. It writes all the output to the specified file.
nohup java -jar /home/my-dir/MyJar.jar > /home/my-dir/log.txt & tail -f /home/my-dir/log.txt &
I am trying to run a unix shell script from java which is available at a particular directory in unix server. This script accepts parameters. I was able to establish SFTP connection and successfully reached to the directory which is holding the shell script. How do i run this script and how to pass parameters? Got few references at https://netjs.blogspot.com/2016/10/how-to-run-shell-script-from-java-program.html
but here the script is available at local system. In my case the script is on server and also accepts parameters.
SFTP is a file transfer protocol (Secure File Transfer Protocol). It lets you transfer the files to and from the server. However, it doesn't let you execute any script on the remote server as that's not what it's designed to do.
If you want to execute a script in remote server then you need to:
Establish an ssh connection
Execute the script from that connection
You need to use a library like JSch, here's an example.
Another way is execute command over SSH.
You create a new script in your localhost (my sample is test.sh) with content as below, and now you can execute it like the way you get from your references.
ssh user#server "sh your-shell-script-in-server.sh"
Read more at
https://www.cyberciti.biz/faq/unix-linux-execute-command-using-ssh/
Java source:
String[] cmd = new String[] { "/bin/sh", "test.sh" };
try {
Process pr = Runtime.getRuntime().exec(cmd);
int rs = pr.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
Your Java function is based on the Runtime object. I'm not sure but I think you can't get the Runtime object of a remote machine, therefore you'll need to put the CLASS-file on that remote machine and launch it up there.
I am trying to start a new process using Runtime.exec(), but my problem lies within using ssh to remote in and then run a java program there. Code:
test = "ssh -t username#host java packageName.ClassName portNumber (Other command line args for this class)"
Process proc = Runtime.getRuntime().exec(new String[] {"/bin/bash", "-c", test});
this doesn't fail or catch, but I need to be able to see the stdout for the newly running process and I don't.
Note: if I run ssh -t username#host java packageName.ClassName portNumber (Other command line args for this class) from the command line it works fine. I have the host setup to not require a password by using ssh keys.
Any ideas?
You need to use Process.getInputStream to obtain the output from the sub-process being created.
See this article for a good discussion on Runtime.exec.
I think you can ask for an input stream that corresponds to the stdout of the process and then print it on your standard output. If you need to see it after it executes, just call waitFor() method on the process so it finishes before you start printing.
Use getInputStream() to access returned process's stdout. You can also use facilities provided by ProcessBuilder.Redirect.
I have a python script that runs on windows and uses win32 extensions and WMI to get some information. If I run the script using the command line, it executes perfectly. But, if I try to run the same script using java Runtime.exec("python myscript.py") it seems to get blocked on the waitFor(). The code is like this:
Process p = Runtime.getRuntime().exec("python myscript.py");
int exitCode = p.waitFor();
If I try to use this same java code with some very simple python script like
print "hello world"
I get the exitCode to be 0, which means it works. Can I execute a python script that imports WMI library, using java Runtime.exec()?
Thanks
One likely reason is that your IO buffers are full and need to be flushed, so try flushing both stdout and stderr from your Process in the java code (example code).
Alternatively, you could try redirecting all output to NUL or a text file with one of the following arguments to exec:
cmd.exe /c python myscript.py > NUL 2>&1
cmd.exe /c python myscript.py > output.txt 2>&1