running linux copy and rename command with java - java

File wd = new File("/bin");
Process proc = null;
try {
proc = Runtime.getRuntime().exec("/bin/bash", null, wd);
} catch (IOException e) {
logger.info(e);
e.printStackTrace();
}
if (proc != null) {
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
//out.println("su - root");
out.println("cp /usr/rock/Masterfile.xls /usr/rock/generatedfile/");
out.println("mv /usr/rock/generatedfile/Masterfile.xls /usr/rock/generatedfile/userid.xls");
try {
String line;
while ((line = in.readLine()) != null) {
logger.info(line);
}
proc.waitFor();
in.close();
out.close();
proc.destroy();
} catch (Exception e) {
logger.info(e);
e.printStackTrace();
}
}
I am trying to copy master file and want to rename according to the userid. Code does not showing any error but i dont see any file in the folder i specify. I tried with sudo root command even its not copying and renaming the file. How should i do in order to run copy and rename command to run successfully from java program.

You're not reading from the process's standard error. So if your cp and mv commands are reporting errors, you won't be seeing them.
It's possible to read from the process's standard error, but that's complicated if you're using Runtime.getRuntime().exec() because reading from standard error needs to be done in a separate thread to reading from standard output.
Java 5 introduced a new class for running external processes: ProcessBuilder. In my opinion, the single biggest advantage of a ProcessBuilder is that you can redirect the standard error of the process into its standard output. That leaves you with only one stream to read from, and hence no need for a separate thread.
I would recommend replacing your use of Runtime.getRuntime().exec(...) with the following:
ProcessBuilder builder = new ProcessBuilder("/bin/bash");
builder.directory(wd);
builder.redirectErrorStream(true);
proc = builder.start();
If the files aren't being copied, then chances are that cp and mv are reporting errors. Making this change should hopefully allow you to see the errors being reported.

Related

Running a .exe file from a Java web app doesn't work

I'm trying to run a .exe file develop in Pascal from my web app(Windows + Primefaces 5 + Tomcat 8). The program generate a text file that I'm gonna read it after but it seems it doens't have the permission to do that, no exceptions were threw.
Here is how I pick the path:
String path = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/WEB-INF/lib/");
projeto.setQtde(1);
this.esquemas = gerenciarProjeto.realizarCorte(projeto, usuario, path+"/");
and here is how I call the program:
Runtime rt = Runtime.getRuntime();
Process pc = rt.exec(this.caminho+"cortebi.exe");
InputStreamReader isr = new InputStreamReader(pc.getErrorStream());
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<ERROR>");
while ( (line = br.readLine()) != null){
System.out.println(line);
}
System.out.println("</ERROR>");
int exitVal = pc.waitFor();
System.out.println("Process exitValue: " + exitVal);
I realized that if I put the .exe file into my project root and run Eclipse as administrator it works. But I do not know how to put it into my web app root to do the same after it's deployed, I've tried to put it in diferent locations and nothing!
I was able to figure out what was the problem. I tought that Runtime.getRuntime().exec() would behave like a tradicional DOS prompt but I was wrong. In fact the problem itself was not a windows or file permission problem but a misconception of how the exec() method works. I wrote a new piece of code:
public void executarCortebi(File file){
try {
Process pc = Runtime.getRuntime().exec("cmd /c start cortebi.exe",null, file);
StreamGobbler error = new StreamGobbler(pc.getErrorStream(), "ERRO");
StreamGobbler output = new StreamGobbler(pc.getInputStream(), "OUTPUT");
error.start();
output.start();
pc.waitFor();
Thread.sleep(800);
} catch (IOException e) {
e.printStackTrace();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
As I said the way the exec() method works is more restricted I found good material here:When Runtime.exec() won't.
Explaining the parameters of getRuntime.exec() used for me, we have the fallow: First the command itself that must be executed(It's noticeable the diferences between the old cold and the new one), second are the arguments for the .exe file wich in this case are none and third is the file that has the path from my .exe program.
Now everything is working!

How to run .sh file, using process builder?

I already create the .sh file, and the inside is:
sudo iptables --flush
sudo iptables -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j DROP
It works normally when I run it on the terminal, but when I use processbuilder, it didn't do anything. No error, but didn't happen anything, this is the code on my java:
Process pb = new ProcessBuilder("/bin/bash","/my/file.sh").start();
I already looking for the answer, but I still failed to run the .sh file, even I do the same thing with people that already done it.
Sorry if this is a bad question, thank you.
Are you sure that the bash is not run? Do you checked the Process object returned by the startmethod? You can get the output value, the output stream, etc. from this objects.
Check your streams and exitvalue for errors... sudo is probably the problem here.
Not necessarily the best code but it gets the job done. Executes a process, takes the process.streams and prints them to System.out. Might helpt to find out what the issue actually is atlest.
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
final Process proc = pb.start();
final StringBuilder builder = new StringBuilder("Process output");
final Thread logThread = new Thread() {
#Override
public void run() {
InputStream is = proc.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
String line;
do {
line = reader.readLine();
builder.append("");
builder.append(line == null ? "" : line);
builder.append("<br/>");
} while(line != null);
} catch (IOException e) {
builder.append("Exception! ").append(e.getMessage());
} finally {
try {
reader.close();
} catch (IOException e) {
builder.append("Exception! ").append(e.getMessage());
}
}
}
};
logThread.start();
int retVal = proc.waitFor();
System.out.println(builder.toString());
From Java API Runtime : http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html
// Java runtime
Runtime runtime = Runtime.getRuntime();
// Command
String[] command = {"/bin/bash", "/my/file.sh"};
// Process
Process process = runtime.exec(command);
Also you should be careful with sudo commands that may ask for root password.

How to execute dos commands in java with administrative privilege?

I was developing a project in Java to scan the File System and this involves executing dos commands in java with administrative privilege.
I already wrote the program to execute simple dos commands in Java.
public class doscmd {
public static void main(String args[]) {
try {
Process p = Runtime.getRuntime().exec("cmd /C dir");
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
} catch (IOException e1) {
} catch (InterruptedException e2) {
}
System.out.println("Done");
}
}
But as you can see this does not allow to execute elevated commands.
I am developing the project in Netbeans IDE and i was hoping if any of you folks could tell me if there is any code in java to get admin privilege instead of converting the file to .exe and then clicking run as administrator.
Your JVM needs to be running with admin-privileges in order to start a process with admin-privileges.
Build your code and run it as an administrator - every process spawned by your class will have administrator privileges as well.
try this code, it works for me:
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);
OutputStream output = child.getOutputStream();
output .write("cd C:/ /r/n".getBytes());
output .flush();
output .write("DIR /r/n".getBytes());
output .close();

How to write output of child process in Java

I have written a java code in Eclipse and i am developing a plug-in which embed a button on workbench. When this button is clicked, it opens a batch file (located in c:/program file/prism 4.0/bin)
The code successfully opens the .bat file ! But my next task is write the output of that batch file on my console. I am using Eclipse IDE version 3.
My code is
MessageConsoleStream out = myConsole.newMessageStream();
out.println("We are on console ! \n Shubham performed action");
try {
ProcessBuilder pb=new ProcessBuilder("C:\\Program Files\\prism-4.0\\bin\\prism.bat");
pb.directory(new File("C:\\Program Files\\prism-4.0\\bin"));
Process p=pb.start();
int exitVal=p.waitFor();
out.println("Exited with error code "+exitVal+" shown and action performed \n");
out.println("Shubham Process Successful");
out.println("Printing on console");
}
catch (Exception e)
{
out.println(e.toString());
e.printStackTrace();
}
}
Do like this:
.....
Process p = pb.start();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String in;
while((in = input.readLine()) != null) {
out.println(in);
}
int exitVal = p.waitFor();
.....
Note that if the batch file writes to standard error your java program must consume it otherwise the p.waitFor() will never return.
Do yourself a big favor and check http://commons.apache.org/exec/. It will take care of all the awful details about managnig an external process: timeout, handling input/output, even creating the command line will be easier and less error prone
Note that to correctly read from the InputStreams of a Process, you should do so on separate Threads. See this similar question.

Java Runtime.exec() program won't output to file

I have a program that takes in a file as an input and produces an xml file as an output. When I call this from the command line it works perfectly. I try calling it from a Java program with the following code.
try
{
Process proc = Runtime.getRuntime().exec(c);
try
{
proc.waitFor();
}
catch(InterruptedException e)
{
System.out.println("Command failed");
}
}
catch(IOException e)
{
System.out.println("Command failed");
e.printStackTrace();
}
The program seems to be running fine, as it creates an xml file; however, the xml file is empty when I open it. I'm not encountering any exceptions in my Java program, so I'm baffled as to what the problem could be. Why would the command line program work fine normally, but then when called from Java not output anything to the file it created. I was thinking maybe it was some sort of permissions thing. I tried running the program as sudo (I'm using Linux) but to no avail. This problem doesn't seem to be anything I could find an answer to online. Hopefully somebody on here might be able to tell what's going on. :)
Get the output and error streams from your process and read them to see what is happening. That should tell you what's wrong with your command.
For example:
try {
final Process proc = Runtime.getRuntime().exec("dir");
try {
proc.waitFor();
} catch (final InterruptedException e) {
e.printStackTrace();
}
final BufferedReader outputReader = new BufferedReader(new InputStreamReader(proc
.getInputStream()));
final BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc
.getErrorStream()));
String line;
while ((line = outputReader.readLine()) != null) {
System.out.println(line);
}
while ((line = errorReader.readLine()) != null) {
System.err.println(line);
}
} catch (final IOException e) {
e.printStackTrace();
}
If there is no output in either stream, then I would next examine the external program and the command being sent to execute it.
Did you try launching the process from outside java?
For me, I wrote a jar file that output a file and ran that from the command line in another java program. It turns out that there was a fundamental check in my jar file that I had forgotten about on the number of characters in an input string (my bad). If the count of the characters was smaller than 8 there was no output file. If the number of characters was greater than 8, the output file came out without any trouble using the following code:
String cmdStr = "java -jar somejar.jar /home/username/outputdir 000000001";
try
{
Runtime.getRuntime().exec(cmdStr);
Runtime.getRuntime().runFinalization();
Runtime.getRuntime().freeMemory();
log.info("Done");
}
catch (IOException e)
{
log.error(System.err);
}
Not sure if I really need everything here but, hey, it works. Note: no waitFor seems to be necessary in my case.
process input (actually output of the process!) and error streams has to be handled before waiting for the process termination.
This should work better
try
{
Process proc = Runtime.getRuntime().exec("anycomand");
BufferedReader outSt = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader errSt = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String line;
while ((line = outSt.readLine()) != null)
{
System.out.println(line);
}
while ((line = errSt.readLine()) != null)
{
System.err.println(line);
}
proc.waitFor();
}
catch (final IOException e)
{
e.printStackTrace();
}
but to understand better how Runtime exec works it is worth reading
the classic article
When Runtime.exec() won't
which provide useful sample code (better than the one above!)

Categories

Resources