shell Command execution Failing when executed from Java - java

When I execute the below command on command line, it shows all the stored procedures and tables in the sybase DB.
printf 'sp_help\ngo\n' | isql -Uxx -Pxxxx -Dxxxxx
But when I do the same thing in java. This does not return any result.
Can anyone tell me what is the problem with my code below:
public class test
{
public static void main(String[] args)
{
String cmd = "printf "+"\'sp_help\ngo\n\'"+"| isql -Uxx -Pxxxx -Dxxxxx" ;
try{
Process p;
p = Runtime.getRuntime().exec(cmd);
p.waitFor();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine())!=null){
System.out.println("Row is :" + line);
} catch(Exception e)
{
System.out.println("Exception Caught : " + e);
}
}
}
EDIT
I executed it as below suggested by Darkdust but still it doesnt work.
try{
Process p;
p = Runtime.getRuntime().exec("sh -c \'printf \"sp_help\ngo\n\" | isql -Uxx -Pxxxxx -Dxxxxxx\'");
p.waitFor();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = reader.readLine())!=null){
System.out.println("Row is :" + line);
}
}
catch(Exception e)
{
System.out.println("Exception Caught : " + e);
}
But the command :
sh -c 'printf "sp_help\ngo\n" | isql -Usa -Psybase11 -Dcnadb'
Works on command line.
I also tried with :
p = Runtime.getRuntime().exec(new String[]{"sh","-c","\'printf \"sp_help\ngo\n\"","|isql -Uxx -Pxxxxx -Dxxxxx\'"});
But with no sucess.

Several things come to mind:
Incomplete PATH environment variable (thus isql can't be found).
If it's a command you provide, instead of messing with PATH you might want to make sure your are you in the correct working directory and call ./isql instead.
Since you're using a pipe, you should let a shell execute this as in sh -c "foo | bar". Otherwise the | isql ... part is passed as argument to printf as well.

Related

Java system command to load sqlite3 db from file fails

I'm trying to use java to run a system command to load a sqlite3 database from a sql file. There is no error in the sql file, it loads ok using the usual method from the command line:
sqlite3 dbname < file.sql
My method:
public void loadSqlFile(String file, boolean tearDown) {
String s = null;
try {
Process p = Runtime.getRuntime().exec(
"/usr/bin/sqlite3 " +
database +
" < " +
file
);
p.waitFor();
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
} catch (IOException e) {
LOGGER.error("Failed to load sql file (" + file + ")");
} catch (InterruptedException e) {
LOGGER.error("Failed to load sql file (" + file + ")");
}
}
The command being run translates to:
/usr/bin/sqlite3 /tmp/infinite_state_machine_root/1535223603610/control/database/ism.db < /tmp/ISMCoreActionPack_sqlite3.sql
And the error I see on stdout is:
Error: near "<": syntax error
I've searched for a lot of examples of running system commands and can't find anything that explains this error, at least to me!
I have tried other commands in there like ps and so on and they seem to run ok.
Any advice?
I'm running this on a MAC if that is significant.
Hi you would need to use ProcessBuilder to run redirect on input. Should be something around these lines.
ProcessBuilder builder = new ProcessBuilder("sqlite3", database);
builder.redirectInput(file);
Process p = builder.start();

Java program not getting output from terminal

I am running my Java program from terminal and I am trying to count the number of files in a certain directory using a linux command in my code; I have managed to get output for all other commands but this one.
My command is: ls somePath/*.xml | wc -l
When I run my command in my code, it appears that it has nothing to output, yet when I run the same exact command in terminal it works just fine and actually outputs the number of xml files in that directory.
Here is my code:
private String executeTerminalCommand(String command) {
String s, lastOutput = "";
Process p;
try {
p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
System.out.println("Executing command: " + command);
while ((s = br.readLine()) != null){//it appears that it never enters this loop since I never see anything outputted
System.out.println(s);
lastOutput = s;
}
p.waitFor();
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
return lastOutput;//returns empty string ""
}
Updated code w/ output
private String executeTerminalCommand(String command) {
String s, lastOutput = "";
try {
Process p = new ProcessBuilder().command("/bin/bash", "-c", command).inheritIO().start();
//Process p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
System.out.println("Executing command: " + command);
while ((s = br.readLine()) != null){
System.out.println("OUTPUT: " + s);
lastOutput = s;
}
System.out.println("Done with command------------------------");
p.waitFor();
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("LAST OUTPUT IS: " + lastOutput);
return lastOutput;
}
output:
Executing command: find my/path -empty -type f | wc -l
Done with command------------------------
1
LAST OUTPUT IS:
To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.
Process p = new ProcessBuilder().command("bash", "-c", command).start();
bash invokes a shell to execute your command and -c means commands are read from string. So, you don't have to send the command as an array in ProcessBuilder.
But if you want to use Runtime then
String[] cmd = {"bash" , "-c" , command};
Process p = Runtime.getRuntime().exec(cmd);
Note: You can check advantages of ProcessBuilder here and features here over Runtime

running grep command in command line and from java code gives different results

When I run the below grep command in terminal, I get the list of line numbers. But when i tried doing the same via java code i didn't any result. I am not sure what went wrong here.
Thank in advance
grep -in "callback recieved" /home/local/ws/ui_auto/UIAutomator/result/test/logs | cut -f1 -d:
public List<Integer> getLineNumbers(String pattern, String file, String pat) {
String[] cmd = { "/bin/sh", "-c", "grep -in \""+ pattern + "\" " + file + " | cut -f1 -d:"}; // > " + file + "_" + pat };
System.out.println(cmd[2]);
Process proc;
List<Integer> rline = new ArrayList<Integer>();
try {
proc = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
rline.add(Integer.parseInt(line));
}
} catch (IOException e) {
System.out.println(e);
}
return rline;
}
As per as our discussion in comments.If putting a sleeep of 1 second has worked for you. Try putting :
proc.waitFor();
Process.waitFor() blocks the current thread until the process has
terminated, at which point the execution control returns to the thread
that spawned the process.
Put it after: proc = Runtime.getRuntime().exec(cmd);

Runtime exec sh does nothing

So I want to execute sh script from java
Code:
String command = "/__data/1.sh";
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", command);
Process p = null;
try {
p = pb.start();
} catch (IOException e) {
System.out.println("Could not execute script");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
try {
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(command + " says: " + line);
}
} catch (IOException e) {
System.out.println("Error reading response");
}
1.sh:
echo Hello
mkdir QWE
echo Hello2
What I got:
/__data/1.sh says: Hello
/__data/1.sh says: Hello2
Mkdir takes no effect
1.sh chmodded to 777
What's the problem?
UPD: oh, my fault, forgot the line, now edited. But the main question is why other commands do not work. Yea, like mkdir.
When I call /bin/bash -c /__data/1.sh from console it works propertly
UPD: oh, it seems, mkdir doesn't work propertly because I did not set full path. Sorry. Solved
You're missing + line at the end of println. That should at least get rid of some of the confusion. Not sure why mkdir isn't working though.

Problem while executing "tar -ztf" command in Java

I am trying to run "tar -ztf /users/home/test.tar.gz | head -1" in Java, which worked when I tried to run it in unix command line directly.
The result of this command will list one line of the file/folder inside of the test.tar.gz.
for example: proj/test/test_dir
But I when I run it in java. it will give this error:
Running command: tar -ztf /users/home/test.tar.gz | head -1
[java] tar: Options `-[0-7][lmh]' not supported by *this* tar
[java] Try `tar --help' for more information.
Any idea what's wrong with it? why is it related to "specify drive and density" option?
The code I have run:
String s = null;
StringBuffer sbOutput = new StringBuffer();
StringBuffer errorInfo = new StringBuffer();
String[] cmd = {"tar", "-ztf", fileName, "|", "head", "-1"};
try
{
Runtime rt = Runtime.getRuntime();
System.out.println("Running command: " + cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + cmd[3] + " " + cmd[4] + " " + cmd[5]);
Process p = rt.exec(cmd);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//If there is an error - only show that
while ((s = stdError.readLine()) != null)
{
errorInfo.append(s + "\n");
}
if (errorInfo.length() > 0)
{
System.out.println(errorInfo.toString());
}
while ((s = stdInput.readLine()) != null) {
sbOutput.append(s + "\n");
}
// wait for end of command execution
try {
p.waitFor();
} catch (InterruptedException ie) {
new LogErrThread(ie).start();
ie.printStackTrace();
}
p.destroy();
if (sbOutput.length() > 0)
{
System.out.println(sbOutput.toString());
}
}
catch (IOException e)
{
new LogErrThread(e).start();
e.printStackTrace();
}
On the command line, the shell is doing the piping for you. Only the arguments before the | are passed to gtar. Your code incorrectly passes the pipe and the rest of the text as arguments to gtar.
Luckily, the solution is simple. You can simply read the first line yourself.
String[] cmd = {"gtar", "-ztf", fileName};
// ...
// Instead of current input loop.
s = stdInput.readLine();
if(s != null) {
sbOutput.append(s + "\n");
}
while (stdInput.readLine() != null) {
// Disregard. Reading to end to prevent hang.
}
To elaborate Matthew's point, the | operator is interpreted by the shell. To run your command without the shell, you would need to launch the programs separately and connect their pipes together (tricky in Java).
If you input is sanitized, you can invoke the shell and give it the command to run. Its the easier approach, though arguably less portable. In general, the SHELL environment variable contains the user's shell. Shells also have a defacto standardized -c option to pass them a command string in argv. If you invoke $SHELL -c [command string], you should get the behavior you want.

Categories

Resources