I'd like to automate a few tasks I am doing on multiple machines. I would like to use Ganymed's SSH2 library for this task. I am already capable of running multiple commands, getting the response from the server as well as a few other small things. The thing is that you can only execute one command per session which is why my execute method looks like the following in order to allow me to use one method for multiple commands:
public String execCmd(String cmd) throws IOException {
sess = conn.openSession();
sess.execCommand(cmd);
InputStream stdout = new StreamGobbler(sess.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
String result = br.readLine();
br.close();
sess.close();
return (result);
}
The thing is that I seem unable to change my user using "su"+username. I read that the "su" command opens a new shell resulting in this issue.
Now - what would be the cleanest method to resolve this? I read about the possibility of opening a shell using this library but I fail to write to it and I seem unable to locate any examples for it.
Thanks in advance.
If you want to execute multiple commands. You have to request a pseudo terminal and start a shell afterwards. From the session object get the outstream to execute the commands.
...
sess.requrequestPTY();
sess.startShell();
Outstream outstream = sess.getStdin();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outstream));
final String cmd = new String(command);
bufferedWriter.write(cmd);
bufferedWriter.flush();
...
Related
Question:
I have to call an exe file passing 2 string arguments. The call has to get executed as a different user
I referred few of the links that I got from hints. Couple of them were using powershell, few were using runas examples and so on.
But with powershell also, I am not sure if I will face the issue of "cannot be loaded because running scripts is disabled on this system".
Just because of this reason, I want to try something authentic.
Tried following approaches
Trying to do it through a call with RunAs command is making my life difficult. (called a batch file with RunAs command passing a separate pass.txt or savecred). savecred was ruled out by most people. Other one did not work as expected.
Powershell, has issues wherein, I always get a userid/password popup, even though I run through a Java file.
I also get an error in the command prompt as here below
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodExcept
ion
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.Power
Shell.Commands.NewObjectCommand
(Sample code attached below)
public class SamplePS {
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime();
String command = "powershell C:\\Users\\Ramu\\Project\\SampleFile.ps1";
//String cmds[] = {"C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", "\\c", "SampleFile.ps"};
System.out.println("1");
Process proc = runtime.exec(command);
InputStream is = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
System.out.println("2");
}
}
My ps1 file is as here below
$credential = New-Object System.Management.Automation.PSCredential <<domain>>\<<user id>>, <<password>>
start-process cmd.exe -arg "/k dir" -Credential $credential
What is the best way to handle this scenario?
Please suggest! I am not sure what approach to take.
Powershell or Perl or any other scripting.
Whatever it be, I have to make a call from Java file.
Please suggest!
Note: For time being, I dont mind the password being sent as a plain text.
The exe file is in Windows machine
Thanks!
Ram
Recently I am trying to write an java application to call SCM.exe to execute the code loading job. However, after I successfully execute the SCM load command via java, I found that I actually cannot really download the code (as using the command line, the password need to be entered after execute the SCM load command). May I know how can I enter this password just after I use the process to run the SCM in java? How can I get the output of the command line and enter something into the command line?
Thanks a million,
Eric
Since I don't know what exactly SCM.exe in your case is, I'm answering only what deals with the input/output redirection requirements in an abstract sense. I assume further that you are calling SCM.exe with whatever parameters it needs through System("...") and this is where you are unable pass any further input (stdin of the called process).
You need, instead, to be able to, upon receiving the request for password, pass it to the stdin of the other process, which is solved by using pipes in the classical sense (since you are presumably on Windows, YMMV). More generally, you are dealing with a very simple case of IPC.
In Java you may find an adequate solution by using ProcessBuilder [1] (never did myself, though -- i'd use things a lot simpler than java for this purpose, but I digress...).
An outline of a solution would be:
call the process, having its input and output being handled as output/input streams from your caller java process.
read the output of your process until you are queried the password
write the password
carry on as needed.
If you need further clarification you may need to give more details about your scenario.
[1] http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
public class test {
public static void main(String[] args){
try {
System.out.println("");
String commands = "C:/swdtools/IBM/RAD8/scmtools/eclipse/scm.exe load -d C:/users/43793207/test -i test -r eric-repo";
// load -d C:/users/43793207/test -i test -r eric-repo
test test=new test();
test.execCommand(commands);
} catch (Exception e) {
e.printStackTrace();
}
}
public void execCommand(String commands){
//ProcessBuilder pb = new ProcessBuilder(Command);
//pb.start();
String line;
try {
//Process pp = Runtime.getRuntime().exec(commands);
System.out.println(commands);
Process process = new ProcessBuilder(commands).start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
We are working on a requirement to execute shell commands from java swing UI.
We need to execute one command to start the session, once the session is started we need to execute some common commands repeatedly.
We are able to execute the commands using the below command.
Runtime.getRuntime().exec("setSession")
Runtime.getRuntime().exec("execute individual task");
this way, everytime we have to set the session and executing the individual tasks.
Is there any way to execute a command (like setSession) once and retain the session to execute the remaining commands?
If I got Your task right, You might want to start a shell on the underlying system, get it's input and output streams and issue Your commands there.
Though that makes You operation system dependent. But commands You executing probably are anyway.
Something like:
Process p = Runtime.getRuntime().exec("cmd.exe");
OutputStream outputStream = p.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
InputStream inputStream = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
writer.write("dir \n");
writer.flush();
i want to open an external app using java.
Process p = Runtime.getRuntime().exec("/Users/kausar/myApp");
this runs the process as i can see in activity monitor.
Now the file i run is actually console app which then takes commands and gives response based on those commands.
for example if i go to terminal and put the same
Kausars-MacBook-Air:~ kausar$ /Users/kausar/myApp
myApp>
Now i can give commands to app as for example
myApp> SHOW 'Hi There'
These are commands taken as keyboard input in the console app, these are not parameters. I have seen different approaches with parameters. I tried the following as well but couldnt get it to work.
String res;
String cmnd = "SHOW \'Hi There\'";
OutputStream stdin = null;
InputStream stdout = null;
stdout = p.getInputStream();
stdin = p.getOutputStream();
stdin.write(cmnd.getBytes());
stdin.flush();
p.waitFor();
BufferedReader input = new BufferedReader(
new InputStreamReader(stdout));
while ((res = input.readLine()) != null) {
System.out.println(res)
}
input.close();
p.destroy();
Its displaying nothing while the same procedure with "/bin/bash -c ls" works just fine.
please help!
Of hand I would say the problem is with p.*wait*For()
Exactly what object and when to usee notify() or notifyAll() call to wake up the object thread would be something like on stdout and maybe a restructure of the process.
note: an interesting feature is the class field in BufferedReader called "lock", the api docs do mention some way of structuring your program so it can be notified.
Say we have this method to make an ssh to another machine. How would I get the output from that machines terminals back to the host machine
public void getSSHreply()
{
Process p;
// Set up the arguments for ProcessBuilder
String[] cmd =
{
"/usr/bin/ssh",
"someRemoteMachine", //This machine will authenticate with keys, hence no pw needed
"./myprog",
};
try
{
p = Runtime.getRuntime().exec(cmd);
//How would I redirect stdout back to host machine?
StringBuffer s = new StringBuffer();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (input.readLine() != null)
{
s.append(input.readLine() + "\n");
}
System.out.println(s.toString());
}
catch (IOException e)
{
System.err.println("Failed to read & or start ");
}
}
The Process object has methods for getting the STDOUT, STDERR, and STDIN streams. (ex. getOutputStream()).
You may want to look into commons-exec for more convenient ways to launch and manager external programs, which has tools like StreamPumper to redirect data.
Unfortunately you can't. The simplest way is probably to read p's inputStream and errorStream (normally in two separate threads).
I believe your immediate problem is because you are using a BufferedReader - so when SSH displays the "Password: " prompt (which doesn't have a terminating line feed) Bufferedreader won't be returning anything to your input.readLine() call.
The easiest thing is to read the input a single character at a time (though not the most efficient, of course).
You'll also probably want to read the stderr stream as well, which is why you might want a couple of threads.