I'm trying a new approach to a hitch I've been stuck on. Instead of using expect4j for my SSH connection, (I couldn't figure out a way past blocking consumer runs and issues with closures, see past posts for more info on that if you're knowledgeable and feeling saintly,) I'm going to try to use an expect script. I have a runtime exec coded in to a button.onclick, see below. Why am I getting a 127 exit value? I basically just need this expect script to ssh in, run a single set of expect and send, give me the readout, and that's it...
I'm using cygwin. Not sure if that's relevant to why this isn't working...is my sh-bang line pointing to the right place? My cygwin install is a full install, all packages, in C:\cygwin.
Why am I getting a 127 exit value instead of a readout from my server, and how do I alleviate this?
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec( new String [] {"C:\\cygwin\\bin\\bash.exe", "C:\\scripts\\login.exp"});
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<OUTPUT>");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
#!/usr/bin/expect -f
spawn ssh userid#xxx.xxx.xxx.xxx password
match_max 100000
expect "/r/nDestination: "
send -- "xxxxxx\r"
expect eof
The problem is that you use bash to execute an expect script. You need to use expect to execute an expect script, or bash to execute an expect script by means of a shell commandline (that would be Process proc = rt.exec( new String [] {"C:\\cygwin\\bin\\bash.exe", "-c", "C:\\scripts\\login.exp"});, note the "-c" which I have inserted) which makes use of the magic shebang at the top of your script. Or better, use only the shebang: Process proc = rt.exec( new String [] {"C:\\scripts\\login.exp"});
The exit value of 127 is a special exit value, and tells you "command not found". Which makes sense as you expect script contains many words for which no system binaries or shell builtins exist.
Related
I'm trying to use Runtime.getRuntime().exec() to call a program as if it was called from the terminal, but it just crashes with a fatal error after reading the first file.
In the terminal I run the command like so:
mace4 -c -f inputFile.in > outputFile.out
It works as expected, reading from the first file and outputting in the second one.
In Java I try to run it this way:
String args[] = new String[]{"mace4", "-c", "-f", inputFileName ,">",outputFileName};
try {
String s;
Process proc = Runtime.getRuntime().exec(args, null, new File("/home/user/workDirectory/"));
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
proc.waitFor();
proc.destroy();
As soon as the program reaches the end of the first file, it throws this:
Fatal error: read_all_input, file > not found
The program is quite old and I can't seem to find a way to get a more detailed error out of it..
I tried calling it with these arguments {"sh or bash", "-c", "mace4", "-c", "-f", inputFileName ,">",outputFileName} which makes the program run and then freeze (or at least nothing appears in the console)..
Am I calling the terminal command wrong and if yes what should I change?
PS: this is my first question here, if I missed anything, I'm sorry..
It looks like you're trying to use the Bash output redirection operator >. This redirects the output of the program you're running to a file (or another program)
This answer explains how to do this using ProcessBuilder which should work for what you're trying to do here.
For example:
ProcessBuilder pb = new ProcessBuilder("mace4", "-c", "-f", inputFileName);
pb.redirectOutput(new File(outputFileName));
Process p = pb.start();
I'm trying to execute a command in my terminal. The problem is, when I execute the command in terminal, it succeed, but when I run the command from java, the command is executed but, I got an error message showing me that some python module is missing.
try{
String[] list = { "python3", "script.py" };
ProcessBuilder pb = new ProcessBuilder(list);
pb.directory(
new File("/home/script"));
System.out.println("" + pb.directory());
Process process = pb.start();
InputStream str = process.getErrorStream();
InputStreamReader isr = new InputStreamReader(str);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:", Arrays.toString(args));
while ((line = br.readLine()) != null) {
System.out.println(line);}
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String ret = in.readLine();
System.out.println("value is : "+ret);
process.waitFor();
process.destroy();
}catch (Exception ex) {
ex.printStackTrace();
}
The error message:
/home/script
Output of running [] is:Traceback (most recent call last):
File "scraper.py", line 8, in <module>
from selenium import webdriver
ModuleNotFoundError: No module named 'selenium'
value is : null
PS: When I execute the command directly from terminal, everything works good, I don't get the missing module error.
Similar to Java, python allows to import other stuff. That message tells you that your python script wants to use the module selenium, but can't find it.
Most likely you have some special ENV var setup when running commands manually in a shell/console. So check your .bashrc or .initrc or whatever defines your ENV variables. On a unix system, typing the command env might show you all settings, too. Simply check if the env var PYTHONPATH is setup.
As that call works from the command line, then for sure, the module is installed on your system. Your only problem is that python can't find it when you invoke that script through the Java ProcessBuilder!
One solution might be that you "manually" adjust the PYTHONPATH from within your script. Thus: figure the correct setup for PYTHONPATH, then update your script to "do the right thing".
For further details, see the python documentation!
I need to run two commands Linux using java code like this:
Runtime rt = Runtime.getRuntime();
Process pr=rt.exec("su - test");
String line=null;
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while((line=input.readLine()) != null) {
System.out.println(line);
}
pr = rt.exec("whoami");
input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Exited with error code "+exitVal);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
The problem is the output of the second command ("whoami") doesn't display the current user which used on the first command ("su - test")!
Is there any problem on this code please?
In the general case, you need to run the commands in a shell. Something like this:
Process pr = rt.exec(new String[]{"/bin/sh", "-c", "cd /tmp ; ls"});
But in this case that's not going to work, because su is itself creating an interactive subshell. You can do this though:
Process pr = rt.exec(new String[]{"su", "-c", "whoami", "-", "test"});
or
Process pr = rt.exec(new String[]{"su", "test", "-c", "whoami"});
Another alternative is to use sudo instead of su; e.g.
Process pr = rt.exec(new String[]{"sudo", "-u", "test", "whoami"});
Note: while none of the above actually require this, it is a good idea to assemble the "command line" as an array of Strings, rather than getting exec to do the "parsing". (The problem is that execs splitter does not understand shell quoting.)
As stated in the Javadoc for Runtime.exec():
Executes the specified string command in a separate process.
each time you execute a command via exec() it will be executed in a separate subprocess. This also means that the effect of su ceases to exist immediately upon return, and that's why the whoami command will be executed in another subprocess, again using the user that initially launched the program.
su test -c whoami
will give you the result you want.
If you want to run multiple commands in a way the commands would execute in a subshell if need be see the response here
How can I run multiple commands in just one cmd windows in Java? (using ProcessBuilder to simulate a shell)
im using the following code to Restore PostgreSQL database using java
Runtime r = Runtime.getRuntime();
Process p;
String cmd ="D:/Program Files/PostgreSQL/9.1/bin/pg_restore.exe --host localhost --port 5432 --username postgres --dbname mytestqq --role postgres --no-password --verbose D:\sathish\rawDatabase.backup";
p = r.exec(cmd);
i have 42 tables in the rawDatabase.backup file but only one table is getting restored why the rest of the tables are not happening whats wrong in my code?
thanks in advance!!!!
It's surprising that the command you show works at all, since you're failing to quote the spaces in the command path. Try:
String[] cmd = {
"D:\\Program Files\\PostgreSQL\\9.1\\bin\\pg_restore.exe",
"--host", "localhost",
"--port", "5432",
"--username", "postgres",
"--dbname", "mytestqq",
"--role", "postgres",
"--no-password",
"--verbose",
"D:\\sathish\\rawDatabase.backup"
};
p = r.exec(cmd);
Changes:
Convert the single-string form to the much safer arguments array form of the exec call;
Double the backslashes in the rawDatabase path since your original command fails to escape backslashes, so \r is a carriage return in the string instead of the \ char followed by the r char.
Switch to doubled backslashes instead of forward slashes on the program path for consistency. This change probably doesn't matter.
Also check the return status of the process. You must use Process.waitFor() then once it has exited use Process.exitValue() to determine the result. You should examine the stderr and stdout captured by the Process object for errors and logging information.
The reason your program continues not to work is probably because:
You have old pg_restore processes hanging around holding locks; and/or
You aren't consuming stdout and stderr so pg_restore runs out of buffered pipe space and blocks writing on the output stream.
This will all be much simpler if you use ProcessBuilder instead. ProcessBuilder lets you provide file streams to write output to and generally takes care of a lot of this for you. You must still wait for the process to terminate and check its return code though.
Finally I got the solution
Runtime r = Runtime.getRuntime();
Process p;
ProcessBuilder pb;
r = Runtime.getRuntime();
pb = new ProcessBuilder(
"D:\\Program Files\\PostgreSQL\\9.1\\bin\\pg_restore.exe",
"--host=localhost",
"--port=5432",
"--username=postgres",
"--dbname=mytestqq",
"--role=postgres",
"--no-password",
"--verbose",
"D:\\sathish\\rawDatabase.backup");
pb.redirectErrorStream(true);
p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String ll;
while ((ll = br.readLine()) != null) {
System.out.println(ll);
}
The following code perfectly work in taking the postgres DB dump using JAVA code..Try this
List<String> cmds = new ArrayList<String>();
cmds.add("C:\\Program Files\\PostgreSQL\\9.1\\bin\\pg_dump.exe");
cmds.add("-i");
cmds.add("-h");
cmds.add("localhost");
cmds.add("-p");
cmds.add("5432");
cmds.add("-U");
cmds.add("YOUR PG USERNAME");
cmds.add("-F");
cmds.add("c");
cmds.add("-b");
cmds.add("-v");
cmds.add("-f");
cmds.add("\"E:\\pg_dump.backup\"");//Location to store db Dump backup
cmds.add("lmd");
ProcessBuilder process = new ProcessBuilder();
process.command(cmds).start();
I am working on a Java program that has to fetch the machine serial number, CPU serial number etc. On Windows, the WMI interface is the best way to query for such information, and the standard way to query using the commandline is
wmic bios get serialnumber
which produces output:
SerialNumber
WWV46RT609A3467173E
Translating this into Java, I have used both Runtime.exec() and a ProcessBuilder like so:
(The commented Process p is what I did previously). Here, component and item correspond to 'bios' and 'serialnumber' in the commandline above.
String ret = "";
ProcessBuilder pb = new ProcessBuilder("wmic", component, "get", item);
pb.redirectErrorStream(true);
// Process p = Runtime.getRuntime().exec(
// "wmic " + component + " get " + item);
Process p = pb.start();
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader input = new BufferedReader(isr);
String str;
while ((str = input.readLine()) != null) {
if (str.equalsIgnoreCase(item) || StringUtils.isBlank(str)) {
continue;
}
ret = str.trim();
}
input.close();
isr.close();
System.out.println(ret);
This snippet works perfectly on Windows 7, but hangs on Windows XP. Using wmic from the commandline works on both OSes.
I read here that there's a problem with handling both stdout and stderr of the called process, hence the redirectErrorStream() call.
Why does it work flawlessly on Windows 7 but fail on XP? Is there a way other than spawning a separate thread, aka 'StreamGobbler'? (The linked example is quite ancient, and predates the ProcessBuilder class, with its redirectErrorStream() call.
I hope that you have by now got a resolution to this issue. If not, this is what you need to do. First, I also encountered with the same issues and came to discover that it is bufferedReader issue. It is gets into a deadlock situation that resulting into windows xp hanging. The solution is to simulate the end of line (eof) to the bufferedreader by appending "<NUL" the the command.
String[] command = {"CMD", "/C", "WMIC COMPUTERSYSTEM GET USERNAME <NUL "} and executing this command.
You have to use threads to capture ouputs (standard & error).
You can also take a look at this Apache library.