Powershell commands on remote machine via openSSH - java

I am trying to connect to a windows machine from a linux machine via openSSH and run some powershell commands on windows box. I cannot install powershell on linux box due to some restrictions.
Manually launching openSSH from linux and then running commands is working perfectly.
I am trying to do same thing in Java, but the problem is that I am not seeing output of powershell commands ran.
Below is the code to reproduce the same:
public class Example {
public static class Writers exte ds Thread {
Process process;
Writers(Process p) {
process =p;
}
public void run() {
try {
OutputStreamWriter writer= new OutputStreamWriter(process.getOutputStream);
String command = "expect -c 'spawn ssh user#host ; expect \"password\" ; send \"passcode\\r\"; interact' \n";
writer.write(command);
writer.write("echo \"hello123\");
writer.flush();
} catch (Exception e) {}
}
public static void main(String[] args) throws Exception {
ProcessBuilder builder = new ProcessBuilder("bash");
builder.redirectErrorStream(true);
Process process = builder.start();
Example.Writers writers = new Example.Writers(process);
writers.start();
BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream()));
String s = null;
while((s= stdout.readLine()) != null) {
System.out.println(s);
}
}
}
OUTPUT:
I see only Windows powershell startup logo and nothing after that.
Tell me why this hello123 not getting printed.
Or, why the powershell output stream not getting redirected to output stream of linux machine ?
manually opening interactive ssh shell and running powershell commands run perfectly, but not via code.

interactive modes don't work nice with scripts and codes and are not recommended. It's better to use some existing ssh framework like jsch to connect, which are available as open source maven dependencies.

Related

Entering a series of commands in git bash through java code

Am trying to get a series of commands on git bash one after the other. I can open the terminal through the code but after that wasn't successful with entering anything. For instance this is the code I tried
String [] args = new String[] {"C:\\Program Files\\Git\\git-bash.exe"};
String something="hi how are you doing";
try {
ProcessBuilder p = new ProcessBuilder();
var proc = p.command(args).start();
var w = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
w.write(something);
} catch (IOException ioException){
System.out.println(ioException);
}
Please let know how to be able to do enter a series of commands into git bash through the code.
The problem is that the command git-bash.exe opens the terminal window but the window's input is still the keyboard, so trying to write to the OutputStream that is returned by method getOutputStream(), in class Process does nothing. Refer to this question.
As an alternative, I suggest using using ProcessBuilder to execute a series of individual git commands. When you do that, your java code gets the command output.
Here is a simple example that displays the git version.
import java.io.IOException;
public class ProcBldT4 {
public static void main(String[] args) {
// C:\Program Files\Git\git-bash.exe
// C:\Program Files\Git\cmd\git.exe
ProcessBuilder pb = new ProcessBuilder("C:\\Program Files\\Git\\cmd\\git.exe", "--version");
pb.inheritIO();
try {
Process proc = pb.start();
int exitStatus = proc.waitFor();
System.out.println(exitStatus);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
When you run the above code, the git version details will be written to System.out.
Also, if the git command fails, the error details are written to System.err.
You need to repeat the code above for each, individual git command that you need to issue.

How to execute zookeeper-server-start .bat file from my java program?

I am trying to spin up zookeeper and kafka servers from my java code. We usually execute the batch files manually, I am trying to automate but the server never starts.
I have tried running other .bat files using the same code and they run like a charm but the zookeeper and kafka-server ones never execute successfully nor do they throw any error
Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c",
"C:/kafka_2.11-2.1.0/kafka_2.11-2.1.0/bin/windows/zookeeper-server-start.bat",
"C:/kafka_2.11-2.1.0/kafka_2.11-2.1.0/config/zookeeper.properties"});
I want the zookeeper server to get started and remain started whereas it doesn't. Please help where am I going wrong, is this even possible?
Below program worked for me, it will print all logs to console and will wait for the process to terminate:
import java.io.*;
public class ExecuteProg {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c",
"E:/Softwares/kafka_2.11-2.0.0/bin/windows/zookeeper-server-start.bat",
"E:/Softwares/kafka_2.11-2.0.0/config/zookeeper.properties"});
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();
}
}
}
I exactly don't know why but adding the "start" flag made it work for me. Now I am able to run both the zookeeper and kafka servers from within the code. The code I am using is as follows,
Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "start",
"C:/kafka_2.11-2.1.0/kafka_2.11-2.1.0/bin/windows/zookeeper-server-start.bat",
"C:/kafka_2.11-2.1.0/kafka_2.11-2.1.0/config/zookeeper.properties"});
Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "start",
"C:/kafka_2.11-2.1.0/kafka_2.11-2.1.0/bin/windows/kafka-server-start.bat",
"C:/kafka_2.11-2.1.0/kafka_2.11-2.1.0/config/server.properties"});

Embed a terminal frame into a JFrame window Java

I've been trying to make an app to act as a ssh / scp client to make transferring files easier from my laptop to my desktop and currently I have been able to get the output of a ls command and get the file tree for the host and remote user, however this requires input in the terminal I am running the app with.
Is it possible to be able to embed a terminal window into a gui as I have went about making an interpreter however things like tab completion and running, for example, python3 don't work. I am also hoping to have full use of a terminal and be able to run commands like vim rather than just print the output of commands which is what I currently have.
My code for executing the commands is:
public void processCmd(String command) {
if (command.equals("exit")) {
System.exit(0);
} else if (command != null && !command.isEmpty()) {
execCommand(command);
}
}
public void execCommand(String input) {
String result = null;
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec(input);
BufferedReader in =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
result += inputLine;
}
in.close();
} catch (IOException e) {
System.out.println("Error");
}
}
The main problem is that when anything like python or vim is run, the app will hang and not do anything, python won't even show up in terminal, however, if I run vim, it will change the terminal screen (not in the app) to mostly vim but without the bottom bar.

How to execute dos commands in java with administrative privilege?

I was developing a project in Java to scan the File System and this involves executing dos commands in java with administrative privilege.
I already wrote the program to execute simple dos commands in Java.
public class doscmd {
public static void main(String args[]) {
try {
Process p = Runtime.getRuntime().exec("cmd /C dir");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
} catch (IOException e1) {
} catch (InterruptedException e2) {
}
System.out.println("Done");
}
}
But as you can see this does not allow to execute elevated commands.
I am developing the project in Netbeans IDE and i was hoping if any of you folks could tell me if there is any code in java to get admin privilege instead of converting the file to .exe and then clicking run as administrator.
Your JVM needs to be running with admin-privileges in order to start a process with admin-privileges.
Build your code and run it as an administrator - every process spawned by your class will have administrator privileges as well.
try this code, it works for me:
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);
OutputStream output = child.getOutputStream();
output .write("cd C:/ /r/n".getBytes());
output .flush();
output .write("DIR /r/n".getBytes());
output .close();

How to execute a interactive shell script using java Runtime?

I am wondering is there any way to execute following shell script, which waits for user input using java's Runtime class?
#!/bin/bash
echo "Please enter your name:"
read name
echo "Welcome $name"
I am using following java code to do this task but it just shows blank console.
public class TestShellScript {
public static void main(String[] args) {
File wd = new File("/mnt/client/");
System.out.println("Working Directory: " +wd);
Process proc = null;
try {
proc = Runtime.getRuntime().exec("sudo ./test.sh", null, wd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Thing is when I execute above program, I believed it will execute a shell script and that shell script will wait for user input, but it just prints current directory and then exits. Is there any way to do this or it is not possible at all in java?
Thanks in advance
The reason it prints the current dir and exits is because your java app exits. You need to add a (threaded) listener to the input and error streams of your created process, and you'll probably want to add a printStream to the process's output stream
example:
proc = Runtime.getRuntime().exec(cmds);
PrintStream pw = new PrintStream(proc.getOutputStream());
FetcherListener fl = new FetcherListener() {
#Override
public void fetchedMore(byte[] buf, int start, int end) {
textOut.println(new String(buf, start, end - start));
}
#Override
public void fetchedAll(byte[] buf) {
}
};
IOUtils.loadDataASync(proc.getInputStream(), fl);
IOUtils.loadDataASync(proc.getErrorStream(), fl);
String home = System.getProperty("user.home");
//System.out.println("home: " + home);
String profile = IOUtils.loadTextFile(new File(home + "/.profile"));
pw.println(profile);
pw.flush();
To run this, you will need to download my sourceforge project: http://tus.sourceforge.net/ but hopefully the code snippet is instructive enough that you can just adapt to J2SE and whatever else you are using.
If you use a Java ProcessBuilder you should be able to get the Input, Error and Output streams of the Process you create.
These streams can be used to get information coming out of the process (like prompts for input) but they can also be written to to put information into the process directly too. For instance:
InputStream stdout = process.getInputStream ();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
String line;
while(true){
line = reader.readLine();
//...
That'll get you the output from the process directly. I've not done it myself, but I'm pretty sure that process.getOutputStream() gives you something that can be written to directly to send input to the process.
The problem with running interactive programs, such as sudo, from Runtime.exec is that it attaches their stdin and stdout to pipes rather than the console device they need. You can make it work by redirecting the input and output to /dev/tty.
You can achieve the same behaviour using the new ProcessBuilder class, setting up the redirection using ProcessBuilder.Redirect.INHERIT.
Note sure at all you can send input to your script from Java. However I very strongly recommend to have a look at Commons Exec if you are to execute external scripts from Java:
Commons Exec homepage
Commons Exec API

Categories

Resources