I am using a Java class to execute a Perl script on a Linux box. The .class is being created successfully.
But when I execute the class, it says exit code successful as sop, but I'm not able to see the Perl output or the execution of the script. If I execute the Perl directly, it works fine...
This is the Perl script:
#!/usr/local/bin/perl
print ("Enter the distance to be converted:\n");
$originaldist = <STDIN>;
chop ($originaldist);
$miles = $originaldist * 0.6214;
$kilometers = $originaldist * 1.609;
print ($originaldist, " kilometers = ", $miles, " miles\n");
And this is my Java class to call the script:
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
class test {
public static void main(String[] args) throws IOException {
String[] aCmdArgs = { "perl", "-e"
, "pl newprg.pl" };
Runtime oRuntime = Runtime.getRuntime();
Process oProcess = null;
try {
oProcess = oRuntime.exec(aCmdArgs);
oProcess.waitFor();
} catch (Exception e) {
System.out.println("error executing " + aCmdArgs[0]);
}
/* dump output stream */
BufferedReader is = new BufferedReader
( new InputStreamReader(oProcess.getInputStream()));
String sLine;
while ((sLine = is.readLine()) != null) {
System.out.println(sLine);
}
System.out.flush();
/* print final result of process */
System.err.println("Exit status=" + oProcess.exitValue());
return;
}
}
Two issues:
perl -e pl newprg.pl will not actually execute your program from the command line, as it will fail to parse the given (non) expression. You probably meant to use perl newprg.pl
Your program requires input, which you will need to pipe in using the output stream of the process
For example:
try {
oProcess = oRuntime.exec(aCmdArgs);
PrintWriter writer = new PrintWriter(new OutputStreamWriter(
oProcess.getOutputStream()));
writer.println(200);
writer.close();
oProcess.waitFor();
} catch (Exception e) {
System.out.println("error executing " + aCmdArgs[0]);
}
Related
I'm developing java code that needs to simulate the following:
my_command < file.txt
I tested writing to STDIN but it doesn't seem to be the solution.
Has someone already developed it?
Note, in the below code,
source is an instance of java.io.File
String commandLine = "myCommand";
Process process = Runtime.getRuntime().exec(commandLine);
new Thread(() -> {
try (BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
Scanner scanner = new Scanner(source)
){
String line;
while (scanner.hasNext()) {
line = scanner.nextLine();
stdin.write(line);
System.out.print(line);
}
stdin.flush();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
int ret = process.waitFor();
FYI my command is mysql
You should use class ProcessBuilder (rather than class Runtime).
I don't know what your my_command is, so the below code uses cleartool.
First I create the text file containing the cleartool subcommands that I wish to execute.
hostinfo
exit
(Note the empty last line of the file.)
I named this file exits_ct.txt
Now the java code that will run cleartool command, then enter the subcommands from the text file and print the command output to standard output.
import java.io.File;
import java.io.IOException;
public class PrcBldTs {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("cleartool");
pb.redirectInput(new File("exits_ct.txt"));
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
try {
Process proc = pb.start(); // throws java.io.IOException
int result = proc.waitFor(); // throws java.lang.InterruptedException
System.out.println("result: " + result);
}
catch (IOException | InterruptedException x) {
x.printStackTrace();
}
}
}
When I run the above code, I get the following output:
MY_COMP: ClearCase 9.0.0.0 (Windows NT 6.2 (build 9200) Pentium)
result: 0
I am trying to call Fortran 90 program from java program,
My Fortran program is as follows:
!sum.for
program Numbers_sum
implicit none
! -----------------------------------------------Declare
REAL :: a,b,sum
! -----------------------------------------------Input
print*,"Enter first number..."
read*, a
print*,"Enter second number ..."
read*, b
! -----------------------------------------------Compute
sum = a+b
! -----------------------------------------------Output
print*,"Sum =", sum
end
Which is working on Fortran compiler. And finally I got an exe file which will execute and give fortran result. I am trying to call it from my java program,
My java program as follows:
import java.io.File;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Sum {
public static void main(String []args) {
String filePath = "sum.exe";
if (new File(filePath).exists()) {
try {
ProcessBuilder pb = new ProcessBuilder(filePath);
pb.redirectError();
Process p = pb.start();
InputStream is = p.getInputStream();
int value = -1;
while ((value = is.read()) != -1) {
System.out.print((char) value);
}
int exitCode = p.waitFor();
System.out.println(filePath + " exited with " + exitCode);
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.err.println(filePath + " does not exist");
}
}
}
But it is not working.
I am calling the java from my command prompt as follows:
But cursor blinking only. It is not working.
I did cntrl+c to escape from the java command prompt . That case I gott like the following:
Why it is not working. Please help me. How I could read that exe from my java program correctly. Any help will be appreciated!!
Seems that you need to redirect streams here--so input stream of fortran execution process would be redirected to System.in and output stream to System.out. Just put the following lines:
pb.redirectInput(Redirect.INHERIT);
pb.redirectOutput(Redirect.INHERIT);
before pb.start().
I recently asked a question that helped me understand what a C program is doing in terms of Java. My goal is now to perform a C-like fork of two new child processes, while keeping track of parent process IDs and child process Ids. I am unsure, however, if this is possible.
Here, I've attempted to initiate process P and run two child processes (which I believed to be the InputStreamReaders isr and wasr ). I've gotten the PID of process P. But, where I'm stuck is the fact that InputStreamReader is not really a process, so I can't get the process ID.
I'll mention like I did in the other post that this is a homework assignment which provides C code instruction but urging Java code responses. The end goal is to be able to print "Child process ID of Parent process ID has begun" and "Child process ID has terminated" -- this is why it's important that I keep track of everyone's ID.
I found this other post, but I'm not sure how to adapt it.
UPDATE : With help of another SO user, I've realized that i may be approaching the problem in the wrong way. Here, parent process is the java process and child process is the native process. Updated code below.
Original Code
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
class processesorigin {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("/bin/ls");
final InputStream is = p.getInputStream();
final InputStream was = p.getInputStream();
Thread t = new Thread(new Runnable() {
public void run() {
InputStreamReader isr = new InputStreamReader(is);
InputStreamReader wasr = new InputStreamReader(was);
int ch;
try {
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
while ((ch = wasr.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
p.waitFor();
t.join();
int pid = 0;
if(p.getClass().getName().equals("java.lang.UNIXProcess")) {
try {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getInt(p);
}
catch (Throwable e) {
}
}
System.out.println("Process " + pid + " terminates.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
UPDATED CODE Using these tips and another SO user, I have found how to capture the Java process ID. There is however, still an issue with signaling of the start of each process. This might be another question though.
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import sun.management.VMManagement;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
class processesorigin {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec("/bin/ls");
Process q = Runtime.getRuntime().exec("/bin/ls");
final InputStream is = p.getInputStream();
final InputStream was = q.getInputStream();
/*get PID of Java process*/
final String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
final String jvmPid = runtimeName.split("#")[0];
int pid = 0;
int qid = 0;
if(p.getClass().getName().equals("java.lang.UNIXProcess")) {
/* get the PID of child processes : native ls command*/
try {
Field f = p.getClass().getDeclaredField("pid");
Field g = q.getClass().getDeclaredField("pid");
f.setAccessible(true);
g.setAccessible(true);
pid = f.getInt(p);
qid = g.getInt(q);
}
catch (Throwable e) {
}
}
final int pidCopy = pid;
final int qidCopy = qid;
Thread t = new Thread(new Runnable() {
public void run() {
InputStreamReader isr = new InputStreamReader(is);
InputStreamReader wasr = new InputStreamReader(was);
int ch;
try {
System.out.print("Child process " + pidCopy + " of Parent process " + jvmPid + " begun.");
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
System.out.print("Child process " + qidCopy + " of Parent process " + jvmPid + " begun.");
while ((ch = wasr.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
p.waitFor();
q.waitFor();
t.join();
System.out.println("Child process " + pidCopy + " terminated.");
System.out.println("Child process " + qidCopy + " terminated.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Regarding your update: The way how you are getting the PID of the native child process should also work on OSX.
Since your assignment is to start two child processes from Java (right?) you can just start two native processes using Runtime.getRuntime().exec(), read and print stdout of each of them, and get and print the PID of each of them.
You can choose to run both processes in the main thread or start each process in a separate thread, basically like it is done in your example.
I am not sure if I fully understand what you want to achieve but maybe this helps you anyway. It is a tiny C program, a kind of wrapper that you can use to start a native process and obtain its PID from Java code:
#include <unistd.h>
#include <stdio.h>
/*
* Purpose of this "program" is to write its PID to stdout so that
* it can be read by a Java program which then can shutdown this
* process gently by sending for example SIGINT to it.
* After printig its PID the process executes the program given
* as argument.
*/
int main(int argc, char *argv[]) {
if(argc < 3) {
fprintf(stderr,"Usage: %s <program> <name> [arg] ...\n", argv[0]);
return -1;
}
/* Write the PID of the process to stdout */
fprintf(stdout,"%i\n", getpid());
/* Flush the buffers */
fflush(NULL);
/*
* Execute the program (specified as file or full path) given as first
* argument in the current process.
*/
return execvp(argv[1], argv + 2);
}
Assuming above code was compiled and the executable copied to /usr/local/bin/jpwrapper, it can be used from Java to run a native process like ls -l /dev, print out the PID when the process started, print its stdout and again the PID when it terminated:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class PID {
public static void main(final String[] args) throws Exception {
final Process process = Runtime.getRuntime().exec(new String[] {
"/usr/local/bin/jpwrapper",
"/bin/ls", "ls", "-l", "/dev"});
String pid = null;
try (final BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
// First line of output from the wrapper is the PID
String line = reader.readLine();
pid = line;
System.out.println(String.format(
"Process with PID %s started", pid));
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
final int exitCode = process.waitFor();
System.out.println(String.format(
"Process with PID %s terminated with exit code %s",
pid, exitCode));
}
}
But, like I already admitted in my comment, getting the PID from UnixProcess is easier (but also hacky).
My requirement is to load a script using sql loader from within my java app. For this purpose, I've been using the following script
D:\oracle\product\10.2.0\db_1\BIN\SQLLDR.EXE userid=myDBUserID/myDBPswrd data=C:\Users\myUserName\Desktop\sql_ldr_files\1\table_export_DATA.ldr control=C:\Users\myUserName\Desktop\sql_ldr_files\1\table_export_DATA.ctl log=C:\Users\myUserName\Desktop\sql_ldr_files\1\logitit.log discard=C:\Users\myUserName\Desktop\sql_ldr_files\1\discard.txt bad=C:\Users\myUserName\Desktop\sql_ldr_files\1\bad.txt
But while trying to run it first on cmd prompt, i realized that the command won't run if I do not run it, on cmd prompt which is launched by "Run as Administrator".
Once the cmd was launched by "Run as Administrator", the command ran successfully, the script executed and the table got populated properly.
Now my task was to use the same code, but run it from within a java code. For this, I've used the following java code,
import java.io.FileWriter.*;
import java.io.BufferedWriter.*;
import java.io.BufferedReader.*;
import java.io.InputStreamReader.*;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RunSqlLrdFromJava
{
public static void main(String s[])
{
try{
Runtime rt = Runtime.getRuntime();
String sqlLoaderPath = "D:\\oracle\\product\\10.2.0\\db_1\\BIN\\";
String runAsCmd="runas /user:myPCName\\administrator ";
String cmd = runAsCmd + "\""+sqlLoaderPath + "SQLLDR.EXE userid=myDBUserID/myDBPswrd "
+ " data=C:\\Users\\myUserName\\Desktop\\sql_ldr_files\\1\\table_export_DATA.ldr"
+ " control=C:\\Users\\myUserName\\Desktop\\sql_ldr_files\\1\\table_export_DATA.ctl"
+ " log=C:\\Users\\myUserName\\Desktop\\sql_ldr_files\\1\\logitit.log"
+ " discard=C:\\Users\\myUserName\\Desktop\\sql_ldr_files\\1\\discard.txt"
+ " bad=C:\\Users\\myUserName\\Desktop\\sql_ldr_files\\1\\bad.txt " + "\"";
try{
FileWriter file = new FileWriter("ExceptionInSqlldr.txt");
BufferedWriter bf = new BufferedWriter(file);
bf.write("SQLLDR COMMAND:\n" +cmd +"---------------------------------\n\n\n");
Process proc = rt.exec(cmd);
int exitVal = proc.waitFor();
BufferedReader br = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
String line;
System.out.println("\n------------------exitVal:"+exitVal+"------------------\n\n");
bf.write("SQLLDR COMMAND:\n" +cmd +"---------------------------------\n\n\n");
if(br!=null && exitVal!=0)
{ while((line = br.readLine()) != null)
{
bf.write("\n"+ line +"\n");
System.out.println("Read from error stream: \"" + line + "\"");
}
}
proc.destroy();
bf.close();
}
catch(Exception e)
{
e.printStackTrace();
//System.out.println(e.getMessage());
}
}
catch(Exception e)
{
e.printStackTrace();
//System.out.println(e.getMessage());
}
}
}
But this time, it won't run.
My problem is, when we use "run as" to run the process as administrator on command prompt, it prompts for a password. Thus when I'm using the same "run as" command from within a java code, I can't provide the response to that prompt [as it seems at the least].
Is there a wayout, where I can run the command as an administrator from within my java code by passing the password for administrator inside the command only, so that my java code becomes successfull in running it?
Please advice as I didn't ever do it before.
Warm regards.
I want to compile the following C codes from a java program (the syntax errors have been intentionally left):
/* Hello World program */
#include<stdio.h>
main()
{
printf("Hello World")
}
I want my java program to compile the C file and give the diagnostics in the console.
Example: Line 4 ; expected and line 5 invalid syntax...
I have installed the CodeBlock MinGW Compiler and have been able to get the codes compiled and got the errors printed out.
Have a look at what I did:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class C_Compile {
public static void main(String args[]){
String ret = compile();
System.out.println(ret);
}
public static String compile()
{
String log="";
String myDirectory = "C:\\";
try {
String s= null;
//change this string to your compilers location
Process p = Runtime.getRuntime().exec("cmd /C gcc hello.c", null, new java.io.File(myDirectory));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
boolean error=false;
log+="\n....\n";
while ((s = stdError.readLine()) != null) {
log+=s;
error=true;
log+="\n";
}
if(error==false) log+="Compilation Successful !!!";
} catch (IOException e) {
e.printStackTrace();
}
return log;
}
public int runProgram()
{
int ret = -1;
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("cmd.exe /c start a.exe");
proc.waitFor();
ret = proc.exitValue();
} catch (Throwable t)
{
t.printStackTrace();
return ret;
}
return ret;
}
}
I got the following results:
....
hello.c: In function 'main':
hello.c:9:1: error: expected ';' before '}' token
But I wanted to know if it's possible to get the diagnostic from a listener. I want to get line numbers, positions, types of the syntax errors which will be later input in an array for further processing.
Below is what I wanted to have like in Java:
http://prntscr.com/sgvya
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<CaptureErrors> myerrors = new ArrayList<CaptureErrors>();
MyDiagnosticListener listener = new MyDiagnosticListener();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(listener, null, null);
String fileToCompile = "C:\\Users\\User\\Desktop\\MyC.java";
Iterable fileObjects = fileManager.getJavaFileObjectsFromStrings(Arrays.asList(fileToCompile));
CompilationTask task = compiler.getTask(null, fileManager, listener, null, null, fileObjects);
Boolean result = task.call();
if(result == true){
System.out.println("Compilation has succeeded");
}
myerrors = listener.getlistofErrors();
for (CaptureErrors e : myerrors)
{
System.out.println("Code: " + e.getCode());
System.out.println("Kind: " + e.getKind());
System.out.println("Line Number: " + e.getLinenumber());
// System.out.println("Message: "+ e.getMessage(Locale.ENGLISH));
//System.out.println("Source: " + e.getSource());
System.out.println("End position: "+ e.getEndposition());
System.out.println("Position: "+ e.getPosition());
System.out.println("\n");
}
instead of Runtime.exec() use ProcessBuilder and redirectErrorStream(true) on it. That way you will be able to capture both stdout and stderr from compiler output. And instead of invoking via cmd /c invoke the gcc executable directly from ProcessBuilder. Check for exit code status from child process. A non 0 exitcode usually means some error in the child process. Then use some regex to extract the error messages and line numbers from the output stream (which would also contain the stderr output of gcc.exe).