I created a simplest Spring-Boot application to test running command, see the completed code below, after click Run 'Application' in InteliJ, console ends up with Process finished with exit code 0, no directory structures in console display.
Run dir c: in terminal returns all the files and directories, seems Process process = Runtime.getRuntime().exec("cmd /c dir C:"); does not run at all.
I put process = Runtime.getRuntime().exec("dir C:");, running application again, this time console output ends up with java.io.IOException: CreateProcess error=2, apparently Java runtime recognized command as invalid.
Why Process process = Runtime.getRuntime().exec("cmd /c dir C:"); does not return any result?
package
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class Application {
public static void main(String[] args) { SpringApplication.run(Application.class); }
#Bean
public CommandLineRunner CommandLineRunnerBean() {
return (args) -> {
Process process = Runtime.getRuntime().exec("cmd /c dir C:");
// process = Runtime.getRuntime().exec("dir C:");
}
}
}
First, code that you posted doesn't compile.
When you write this line of code:
Process process = Runtime.getRuntime().exec("cmd /c dir C:");
Process is executed, but you need to write code that will display result of this process in console.
You can get result of process by calling :
process.getInputStream()
getInputStream() method gets the input stream of the subprocess. The stream obtains data piped from the standard output stream of the process represented by Process object.
Third, to display all directories in C drive, you should use this path:
Process process = Runtime.getRuntime().exec(String.format("cmd /c dir %s", "C:\\"));
To summarize, if you want to see all directories in your C: drive, first you will need to create a class which will used to output result of process to java console as I mentioned above.
Let's call that class HelperReader.
Here is the code:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.function.Consumer;
public class HelperReader implements Runnable {
private InputStream inputStream;
private Consumer<String> consumer;
public HelperReader(InputStream inputStream, Consumer<String> consumer) {
this.inputStream = inputStream;
this.consumer = consumer;
}
#Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines()
.forEach(consumer);
}
}
Change code in your Application class to something like this:
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.concurrent.Executors;
#SpringBootApplication
public class Application implements CommandLineRunner {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
#Override
public void run(String... args) throws Exception {
Process process = Runtime.getRuntime().exec(String.format("cmd /c dir %s", "C:\\"));
HelperReader streamGobbler =
new HelperReader(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
}
}
Run the application and you should see something like following picture in console.
Related
I am building a CLI tool that is running the following Maven command
mvn archetype:generate -B -DarchetypeGroupId=me.pablo -DarchetypeArtifactId=fleeti-archetype -DarchetypeVersion=1.0 -Dversion=1.0 -DgroupId=me.pablo -Dpackage=me.pablo -Dname=Test -DartifactId=test
it's supposed to run this command in the following directory
C:\Users\35356\Desktop\Test
Now, I created my own utility class to run the commands I need using ProcessBuilder:
package me.pablo.processes;
import me.pablo.FleetiMessage;
import me.pablo.FleetiMessageType;
import me.pablo.commands.Command;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.Arrays;
public class FleetiProcess
{
private List<Command> commands;
private List<Process> allProcesses;
public FleetiProcess(final List<Command> commands) {
this.commands = commands;
this.allProcesses = new ArrayList<>();
}
public void execute() {
runProcess();
}
public void executeAsync(final int delayInSeconds) {
Executors.newSingleThreadScheduledExecutor().schedule(this::runProcess, delayInSeconds, TimeUnit.SECONDS);
}
public void execute(final int delayInSeconds) {
Executors.newSingleThreadScheduledExecutor().schedule(this::stopFleetiProcess, delayInSeconds, TimeUnit.SECONDS);
runProcess();
}
public void stopFleetiProcess() {
allProcesses.forEach(Process::destroyForcibly);
}
private void runProcess() {
commands.forEach(command -> {
// Debug messages
System.out.println("Raw command is \n" + command.getRawCommand());
System.out.println("Split command is \n" + Arrays.toString(command.getRawCommand().split(" ")));
System.out.println("Target file exist: \n" + new File(command.getPath()).exists());
final ProcessBuilder commandBuilder = new ProcessBuilder();
commandBuilder.command(command.getRawCommand().split(" "));
commandBuilder.directory(new File(command.getPath()));
try {
final Process commandProcess = commandBuilder.start();
final StreamGobbler streamGobbler = new StreamGobbler(commandProcess.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
allProcesses.add(commandProcess);
int exitVal = commandProcess.waitFor();
if (exitVal == 0) {
FleetiMessage.printMessage(
new FleetiMessage(FleetiMessageType.SUCCESS, "Successfully ran process for " + command.getRawCommand()));
} else {
FleetiMessage.printMessage(
new FleetiMessage(FleetiMessageType.ERROR, "Could not run process for command " + command.getRawCommand()));
}
} catch (final IOException | InterruptedException e) {
e.printStackTrace();
}
});
}
private static class StreamGobbler implements Runnable {
private InputStream inputStream;
private Consumer<String> consumer;
StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
this.inputStream = inputStream;
this.consumer = consumer;
}
#Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines()
.forEach(consumer);
}
}
}
Every time I run this code, I run into the same error:
java.io.IOException: Cannot run program "mvn" (in directory "C:\Users\35356\Desktop\Test"): CreateProcess error=2, The system cannot find the file specified
I've researched this problem, and I've tried the suggested solutions: trying to pass the command in the ProcessBuilder constructor, running the command as a single String, and making sure the file actually exists.
However, I know for a fact that the file exists. This is the complete console output:
Raw command is
mvn archetype:generate -B -DarchetypeGroupId=me.pablo -DarchetypeArtifactId=fleeti-archetype -DarchetypeVersion=1.0 -Dversion=1.0 -DgroupId=me.pablo -Dpackage=me.pablo -Dname=Test -DartifactId=test
Split command is
[mvn, archetype:generate, -B, -DarchetypeGroupId=me.pablo, -DarchetypeArtifactId=fleeti-archetype, -DarchetypeVersion=1.0, -Dversion=1.0, -DgroupId=me.pablo, -Dpackage=me.pablo, -Dname=Test, -DartifactId=test]
Target file exist:
true
java.io.IOException: Cannot run program "mvn" (in directory "C:\Users\35356\Desktop\Test"): CreateProcess error=2, The system cannot find the file specified
at java.base/java.lang.ProcessBuilder.start(Unknown Source)
at java.base/java.lang.ProcessBuilder.start(Unknown Source)
at me.pablo.processes.FleetiProcess.lambda$runProcess$0(FleetiProcess.java:53)
at java.base/java.lang.Iterable.forEach(Unknown Source)
at me.pablo.processes.FleetiProcess.runProcess(FleetiProcess.java:43)
at me.pablo.processes.FleetiProcess.execute(FleetiProcess.java:26)
at me.pablo.commands.FleetiCreateAppCommand.run(FleetiCreateAppCommand.java:89)
at picocli.CommandLine.executeUserObject(CommandLine.java:1729)
at picocli.CommandLine.access$900(CommandLine.java:145)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2101)
at picocli.CommandLine$RunLast.handle(CommandLine.java:2068)
at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:1935)
at picocli.CommandLine.execute(CommandLine.java:1864)
at me.pablo.FleetiCLI.main(FleetiCLI.java:19)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.base/java.lang.ProcessImpl.create(Native Method)
at java.base/java.lang.ProcessImpl.<init>(Unknown Source)
at java.base/java.lang.ProcessImpl.start(Unknown Source)
... 14 more
I ran this code in MacOS and worked perfectly. I am only having this issue when running on a Windows. Does anyone know what could be the issue?
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
public class TestUnZip {
public static void main(String[] args) throws IOException, InterruptedException{
String destFolder="E:\\TestScript";
/*
* Location where the Nodejs Project is Present
*/
System.out.println(destFolder);
String cmdPrompt="cmd";
String path="/c";
String npmUpdate="npm update";
String npm="npm";
String update="update";
File jsFile=new File(destFolder);
List<String> updateCommand=new ArrayList<String>();
updateCommand.add(cmdPrompt);
updateCommand.add(path);
updateCommand.add(npmUpdate);
runExecution(updateCommand,jsFile);
}
public static void runExecution(List<String> command, File navigatePath) throws IOException, InterruptedException{
System.out.println(command);
ProcessBuilder executeProcess=new ProcessBuilder(command);
executeProcess.directory(navigatePath);
Process resultExecution=executeProcess.start();
BufferedReader br=new BufferedReader(new InputStreamReader(resultExecution.getInputStream()));
StringBuffer sb=new StringBuffer();
String line;
while((line=br.readLine())!=null){
sb.append(line+System.getProperty("line.separator"));
}
br.close();
int resultStatust=resultExecution.waitFor();
System.out.println("Result of Execution"+(resultStatust==0?"\tSuccess":"\tFailure"));
}
}
The Above Program works fine, but this program is depend on Windows Machine, I want to run the same program in other Machine as well.
1) NPM is a Command comes as a bundle of NodeJS. (I run NodeJS as a service, I have defined the Environment Variable, so I can run npm update command from any folder)
2) I can't find a work around to run the npm update command without using the "cmd", "/c". If I do I get following error
Exception in thread "main" java.io.IOException: Cannot run program "npm update" (in directory "E:\TestScript"): CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
3) Do we have option of Running the npm update command as a parameter of Node.exe. If so can anyone provide me the proper work around.
4) Same as I like, I use mocha framework to run the test script and result generates the .xml file.
5) I want mocha command also being invoked using process builder.
The problem is that ProcessBuilder does not respect the PATHEXT variable on Windows.
It's true there is no npm binary on Windows, there's a npm.cmd. My best solution is to check the platform. Something like this:
static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}
static String npm = isWindows() ? "npm.cmd" : "npm";
static void run() {
Process process = new ProcessBuilder(npm, "update")
.directory(navigatePath)
.start()
}
In Unix or Linux os , the PathBuilder takes the default environment path , so we have to change the environment path and run the npm command through the bash.
import java.io.File;
import java.util.Map;
public class CommandExecutor {
public void exceuteCommand(String commandString,String
directoryToExecuteCommand) {
try {
ProcessBuilder processBuilder = new ProcessBuilder(new String{"bash", "-c",commandString});
Map<String, String> env = processBuilder.environment();
processBuilder.directory(new File(directoryToExecuteCommand));
String envPath="/home/admin123/.nvm/versions/node/v10.15.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin";
env.put("PATH",envPath);
processBuilder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
CommandExecutor commandExecutor=new CommandExecutor();
commandExecutor.exceuteCommand("npm install", "/home/admin123/Desktop");
}
}
I have a file
import java.io.IOException;
import java.nio.file.Paths;
import java.util.*;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.*;
import org.apache.hadoop.mapreduce.lib.output.*;
import org.apache.hadoop.util.*;
public class ViewCount extends Configured implements Tool {
public static void main(String args[]) throws Exception {
int res = ToolRunner.run(new ViewCount(), args);
System.exit(res);
}
public int run(String[] args) throws Exception {
//Path inputPath = new Path(args[0]);
Path inputPath = Paths.get("C:/WorkSpace/input.txt");
Path outputPath = Paths.get("C:/WorkSpace/output.txt");
Configuration conf = getConf();
Job job = new Job(conf, this.getClass().toString());
I try to run a the app in windows. How can I set inputPath and outputPath? The method I use now doesn't work. Before I had
Path inputPath = new Path(args[0]);
Path outputPath = new Path(args[1]);
and I had to go to the command line. Now I want to run the app from the IDE.
I'm getting
Required:
org.apache.hadoop.fs.Path
Found:
java.nio.file.Path
For Eclipse, you could set arguments :
Run -> run configuration -> arguments.
It should be the same in Intellij.
The error tells you that it is expecting a org.apache.hadoop.fs.Path, but instead it receives a java.nio.file.Paths.
This means that you should change the second import of your code to
org.apache.hadoop.fs.Path. IDEs import suggestions can be wrong some times ;)
Change the import and then use the method that you already had to add the input and output path. Those arguments are given in Eclipse with right-clicking the project -> Run as -> Run configurations -> arguments. The two paths should be white-space separated. Apply and run!
For the next executions, just run the project.
I created a really simple project to test reading a directory or file using getClass().getResource('...').getPath() from STS, Tomcat, and running the JAR/WAR file from the terminal with the embedded Tomcat.
Like I said, the project is simple, here's the code:
package org.example
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
#SpringBootApplication
class ResourceDemoApplication implements CommandLineRunner {
static void main(String[] args) {
SpringApplication.run ResourceDemoApplication, args
}
#Override
void run(String... arg0) throws Exception {
retrieveDirectory()
}
void retrieveDirectory() {
/*new File(getClass().getResource('/private/folders').getPath()).eachDirRecurse() { dir ->
dir.eachFileMatch(~/.*.txt/) { file ->
println(file.getPath())
}
}*/
println new File(getClass().getResource('/private/folders/').getPath()).isDirectory()
}
}
When this code runs in STS or if I drop it in a running Tomcat instance, it prints true. When I run it as java -jar..., it returns false in the terminal. I have looked at countless examples and I still don't understand how to get this to work properly or as expected. I know that reading files from inside the JAR is different than having access to the file system, but I'm not sure how to get this to work regardless of how it's deployed.
Thank you in advance for the help!
After quite a bit of research and digging into the code, I ended up with this solution:
package org.example
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.core.io.FileSystemResource
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
#SpringBootApplication
class ResourceDemoApplication implements CommandLineRunner {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver()
static void main(String[] args) {
SpringApplication.run ResourceDemoApplication, args
}
#Override
void run(String... arg0) throws Exception {
retrieveDirectory()
}
void retrieveDirectory() {
List<FileSystemResource> files = resolver.findPathMatchingResources('private/folders/**/example.txt')
files.each { file ->
println file.getInputStream().text
}
}
}
With groovy you don't need to declare types etc... I am doing it for the sake of documentation here to show what's happening in the code. If you do this in Java you will need something like this to replace println file.getInputStream().text:
InputStream is
BufferedReader br
String fileContents
files.each { file ->
is = file.getInputStream()
br = new BufferedReader(new InputStreamReader(is))
String line
fileContents = ""
while((line = br.readLine()) != null) {
fileContents += line
}
println fileContents
println "************************"
br.close()
}
import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executor;
import com.jacob.com.LibraryLoader;
import autoitx4java.AutoItX;
public class SilentInstallation {
public static void main(String[] args) throws IOException, InterruptedException {
String[] cmd = { "C:\\WINDOWS\\system32\\cmd.exe", "/c", "start" };
try {
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(cmd);
}
catch (java.io.IOException exception) {
System.out.println("Caught IOException: " + exception.getMessage());
}
}
}
Here is my code in which I am running command prompt using java. But the problem here I am facing is I can't be able to change the path in command prompt using java code.
Since this code is using in Automation, so is there any command or method in java that can be used to change the path in the command prompt.
I have also used ProcessBuilder to change the directory path.
Any Recommendations.....
This should be enough:
Process p = ...
p.getOutputStream().write("cd d:\\/r/n".getBytes());