exec does not execute a command in your shell
try
CopyProcess p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});
instead.
EDIT:: I don't have csh on my system so I used bash instead. The following worked for me
CopyProcess p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"});
Answer from KitsuneYMG on Stack Overflowexec does not execute a command in your shell
try
CopyProcess p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});
instead.
EDIT:: I don't have csh on my system so I used bash instead. The following worked for me
CopyProcess p = Runtime.getRuntime().exec(new String[]{"bash","-c","ls /home/XXX"});
Use ProcessBuilder to separate commands and arguments instead of spaces. This should work regardless of shell used:
Copyimport java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(final String[] args) throws IOException, InterruptedException {
//Build command
List<String> commands = new ArrayList<String>();
commands.add("/bin/cat");
//Add arguments
commands.add("/home/narek/pk.txt");
System.out.println(commands);
//Run macro on target
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/home/narek"));
pb.redirectErrorStream(true);
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null, previous = null;
while ((line = br.readLine()) != null)
if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
System.out.println(line);
}
//Check result
if (process.waitFor() == 0) {
System.out.println("Success!");
System.exit(0);
}
//Abnormal termination: Log command parameters and output and throw ExecutionException
System.err.println(commands);
System.err.println(out.toString());
System.exit(1);
}
}
Videos
You won't be able to run commands that affect the current invoking shell, only to run command line bash/cmd as sub-process from Java and send them commands as follows. I would not recommend this approach:
CopyString[] cmd = new String[] { "/bin/bash" }; // "CMD.EXE"
ProcessBuilder pb = new ProcessBuilder(cmd);
Path out = Path.of(cmd[0]+"-stdout.log");
Path err = Path.of(cmd[0]+"-stderr.log");
pb.redirectOutput(out.toFile());
pb.redirectError(err.toFile());
Process p = pb.start();
String lineSep = System.lineSeparator();
try(PrintStream stdin = new PrintStream(p.getOutputStream(), true))
{
stdin.print("pwd");
stdin.print(lineSep);
stdin.print("cd ..");
stdin.print(lineSep);
stdin.print("pwd");
stdin.print(lineSep);
};
p.waitFor();
System.out.println("OUTPUT:"+Files.readString(out));
System.out.println("ERROR WAS: "+Files.readString(err));
}
This also works for CMD.EXE on Windows (with different commands). To capture the response per command you should replace use of pb.redirectOutput() with code to read pb.getInputStream() if you really need the responses per line rather than as one file.
On Windows to start a command shell from Java program, you can do it as follows:
Copyimport java.io.IOException;
public class Command {
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("cmd.exe /c start");
} catch (IOException e) {
e.printStackTrace();
}
}
}
You need to use the same approach for Linux.