Java system command to load sqlite3 db from file fails - java

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();

Related

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

java run bash script, command not found

I tried to use java to run some bash script and store the terminal output in a string. However, there are a lot of commands don't work in this way. It keeps showing command not found, but I can run those commands correctly in terminal, ex node --version, go --version. I guess is the path issue, but have no idea how to fix it.
Another question, when I run "python --version", it shows "Python 2.7.10" but it is in getErrorStream. Can anyone give me some hint?
public static void runscript() throws IOException {
Runtime rt = Runtime.getRuntime();
String[] commands = { "/bin/bash", "-c", "node --version" };
Process proc = null;
try {
proc = rt.exec(commands);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
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);
}
}
Reply #VishalKamat comment.
when I tried using the output of "which node" as my path, which is "/usr/local/bin/node". It works!!!
But, does that mean I have to change the path when I need to get different application version info?
I thought I can easily get the info just like I do in terminal.
I try to print $PATH by java in this way
String[] commands = { "/bin/bash","-c", "$PATH" };
The error msg is :
/bin/bash: /usr/bin:/bin:/usr/sbin:/sbin: No such file or directory

shell Command execution Failing when executed from 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.

How to get output from a .bat process to display in a JTextPane?

My program requires that I run a .bat file which will compile java source. This is running fine, however I am looking for a solution which will get the output (and possible errors) of compile.bat and add it to a text pane on a GUI. I have the following code, however when executed the process happens without printing anything to the pane and without any errors.
GenerationDebugWindow.main(null);
Process process = rut.exec(new String[] {file.getAbsolutePath() + "\\compile.bat"});
Scanner input = new Scanner(process.getInputStream());
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
int exit = -1;
while ((line = reader.readLine()) != null) {
// Outputs your process execution
try {
exit = process.exitValue();
GenerationDebugWindow.writeToPane(line);
System.out.println(line);
if (exit == 0) {
GenerationDebugWindow.writeToPane("Compilation Finished!");
if(new File(file + "/mod_" + WindowMain.modName.getText()).exists()){
GenerationDebugWindow.writeToPane("Compilation May Have Experienced Errors.");
}
}
} catch (IllegalThreadStateException t) {
}
}
GenerationDebugWindow
private static JTextPane outputPane;
public static void writeToPane(String i){
outputPane.setText(outputPane.getText() + i + "\r\n");
}
Use:
Runtime.getRuntime().exec( "cmd.exe /C " + file.getAbsolutePath() + "\\compile.bat" );
Reference this question: Java Process with Input/Output Stream
It's likely that the output of the process is going to the error stream. However, ProcessBuilder is a more useful class than directly using System.getRuntime().exec()
In the example below, we're telling the ProcessBuilder to redirect the error stream to the same stream as the output goes to, which simplifies the code.
ProcessBuilder builder = new ProcessBuilder("cmd.exe /C " + file.getAbsolutePath() + "\\compile.bat");
builder.redirectErrorStream(true);
builder.directory(executionDirectory); // if you want to run from a specific directory
Process process = builder.start();
Reader reader = ...;
String line = null;
while ((line = reader.readLine ()) != null) {
System.out.println ("Stdout: " + line);
}
int exitValue = process.exitValue();
My program requires that I run a .bat file which will compile java source.
Your users on *nix and OS X require that source be compiled using the JavaCompiler.
The STBC is an example of using the JavaCompiler. It is open source. It uses a JTextArea as opposed to a JTextPane to hold the source and errors, but should be trivial to adapt.

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