While trying to run a simple HelloWorld Unix executable:
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!" << endl;
}
(Compiled through g++ HelloWorld.cpp -o HelloWorld (on Mac). The program works on my Mac by using ./HelloWorld and by letting it run through a Java environment:
(HelloWorld.java -> working)
public class HelloWorld
{
public static void main(String args[])
{
String[] command = new String[]{"/system/bin/chmod", "744",
"/Developer/Java/HelloWorld" };
execute(command);
command = new String[]{"./HelloWorld"};
execute(command);
}
public static void execute(String...command)
{
StringBuilder log = new StringBuilder();
try
{
BufferedReader br;
String line;
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process proc = builder.start();
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ( (line = br.readLine()) != null)
System.out.println(line + "\n");
}
catch (IOException e) {
log.append("General IOException:\n" + e.getMessage() + "\n");
}
catch (InterruptedException e) {
log.append("Error:\n" + e.getMessage() + "\n");
}
}
}
In my java code for the Android app, I first copied the executable to getBaseContext().getDataDir(), this works fine. To change the permissions I'm using the following:
command = new String[]{"/system/bin/chmod", "744",
getAssetsPath() + "/HelloWorld" };
execute(pv, command);
and trying to run the program through:
command = new String[]{"." + getAssetsPath() + "/HelloWorld"};
terminal(tv, command);
Note, that I use the following functions:
public File getAssetsDir() {
return getBaseContext().getDataDir();
}
public String getAssetsPath() {
return getAssetsDir().getAbsolutePath();
}
public void execute(TextView tv, String...command)
{
tv.setText("Starting Terminal.\n");
StringBuilder log = new StringBuilder();
try
{
BufferedReader br;
String line;
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process proc = builder.start();
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ( (line = br.readLine()) != null)
log.append(line + "\n");
}
catch (IOException e) {
log.append("General IOException:\n" + e.getMessage() + "\n");
}
catch (InterruptedException e) {
log.append("Error:\n" + e.getMessage() + "\n");
}
tv.setText(log.toString());
}
As already said this will result in the following error inside the TextView (tested on Pixel_XL_API_25):
syntax error: '__TEXT' unexpected
Hope you can help me find the cause of this problem. Thanks in advance.
Edit:
If you want to know why I want to use a Unix executable for such simple things: This is just for testing. Actually, I want to run other more complex programs/libraries which will be hard to use through ndk, because there is no cmake for this library, only "normal" make.
The answer is, that the compiler isn't the right compiler to use. If you want to run it on another device you have ti compile it there or use some cross compiler, I guess.
The question is now: Which compiler would work? I found this suggestion (How to compile and run a C/C++ program on the Android system):
arm-linux-gnueabi-g++ -static -march=armv7-a HelloWorld.c -o HelloWorld
But that won't work in this specific constellation.
I want to test to run mysqldump command in my function but I could not create aaadumpdb.sql file. My code is below:
#Test
public void dumpDB() {
Process p = null;
try {
Runtime runtime = Runtime.getRuntime();
p = runtime
.exec("mysqldump -u root -padmin --add-drop-database aaa_db "
+ "D:\\backupdenemeaaa " + "aaadumpdb.sql");
// change the dbpass and dbname with your dbpass and dbname
int processComplete = p.waitFor();
if (processComplete == 0) {
System.out.println("Backup created successfully!");
} else {
JOptionPane.showMessageDialog(new JDialog(),
"Could not create the backup");
}
} catch (Exception e) {
e.printStackTrace();
}
File f = new File("aaadumpdb.sql");
assertTrue(f.exists());
}
Can anybody give me some advice about it? Thank you.
I did some edit in my code but when I run, my code enter into else structure. What can be the problem?
My editted code is below:
#Test
public void dumpDB() {
Process p = null;
try {
Runtime runtime = Runtime.getRuntime();
String mysqldumpExecutable = "C:\\Program Files\\MySQL\\MySQL Server 5.6\\bin\\mysqldump.exe";
p = runtime.exec(mysqldumpExecutable + " -uroot -padmin --add-drop-database -B aaa_db -r" + "D:\\backupdenemeaaa " + "\\aaadumpdb.sql");
// change the dbpass and dbname with your dbpass and dbname
int processComplete = p.waitFor();
if (processComplete == 0) {
System.out.println("Backup created successfully!");
} else {
JOptionPane.showMessageDialog(new JDialog(),
"Could not create the backup");
}
} catch (Exception e) {
e.printStackTrace();
}
File f = new File("aaadumpdb.sql");
assertTrue(f.exists());
How can I solve this problem? Thank you.
The stacktrace would really help to debug it, but I believe you can check if "mysqldump" is in your PATH or the application will simple not find the executable. If you don't want to mess around with your PATH you can hardcode the path to the executable like below:
String mysqldumpExecutable = "C:\\apps\\mysql\\mysqldump.exe";
runtime.exec(mysqldumpExecutable + "-u root -padmin --add-drop-database aaa_db (.....));
When you say you can't create the file what exactly does that mean? Are you getting an error? Nothing happens? Help us help you.
Add the below snippet to find what exactly is happening
try
{
InputStreamReader isr = new InputStreamReader(process.getErrorStream());
BufferedReader br = new BufferedReader(isr,4094);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + "> " + line);
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
You will be aware of the the exceptions and errors that might occur in that Process execution
This might be an easy one - but it's driving me nuts at this point. I'm trying to run SoX from Processing which on my mac computer is running smoothly and with no problems. I need to migrate the code to a windows 7 machine but can't get it to work for some reason. Talking to the terminal from processing works fine. I'm in the right folder (sketch data folder where SoX is also intalled) since I can run commands like "dir" etc. and get the right content printed - but as soon as I try to run sox.exe nothing happens (getting an exit value 1). Running sox.exe straight from the cmd terminal works fine. Here is a sample of what I'm trying to do:
void playBackYear (){
soxPlay = "cmd /c sox.exe year.wav -d";
println (soxPlay);
try {
File workingDir = new File(sketchPath("data"));
Process p=Runtime.getRuntime().exec(soxPlay, null, workingDir);
p.waitFor();
BufferedReader reader=new BufferedReader(
new InputStreamReader(p.getInputStream())
);
String line;
while ( (line = reader.readLine ()) != null)
{
println(line);
}
int exitVal = p.waitFor();
System.out.println("Exited with error code "+exitVal);
}
catch(IOException e1) {
System.err.println("Caught IOException: " + e1.getMessage());
System.out.println( "error 1" );
}
catch(InterruptedException e2) {
System.err.println("Caught IOException: " + e2.getMessage());
System.out.println( "error 2" );
}
}
So the questions is what am I doing wrong here?
Any help is appreciated.
I have written a small wrapper application that wraps sox binary in java. If you are interested in the full project, check it out on GitHub: sox java wrapper project
This is, how i have solved the problem:
private List<String> arguments = new ArrayList<String>();
// add sox arguments to this list above
public void execute() throws IOException {
File soxBinary = new File(soXBinaryPath);
if (!soxBinary.exists()) {
throw new FileNotFoundException("Sox binary is not available under the following path: " + soXBinaryPath);
}
arguments.add(0, soXBinaryPath);
logger.debug("Sox arguments: {}", arguments);
ProcessBuilder processBuilder = new ProcessBuilder(arguments);
processBuilder.redirectErrorStream(true);
Process process = null;
IOException errorDuringExecution = null;
try {
process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
logger.debug(line);
}
} catch (IOException e) {
errorDuringExecution = e;
logger.error("Error while running Sox. {}", e.getMessage());
} finally {
arguments.clear();
if (process != null) {
process.destroy();
}
if (errorDuringExecution != null) {
throw errorDuringExecution;
}
}
}
I want to automatically change the ip address of an Ubuntu 12.04 PC by a program fires at startup. For some certain reasons, I want to code it in Java.
Exactly the solution is written here:
Java - Execute a .SH file
But it does not work in my case. I could not manage to find why,essentially my case is a special case of so called thread, I try to run a sudo-command in linux with
public static void executeCommandLine(String strCommand){
Runtime rt = Runtime.getRuntime();
try {
Process p = rt.exec(strCommand);
if(p==null){
System.out.println("Error in process");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
try {
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
I call this executeCommandLine() function from another function as follows:
public static void changeIpAddress(String strIpAddress, String strRootPassword, String strEthDevice){
String strCommandLine = "";
if(PLATFORM == PLATFORM_LINUX){
strCommandLine = "/bin/echo " + strRootPassword + "| sudo -S /sbin/ifconfig " + strEthDevice + " " + strIpAddress;
}else if(PLATFORM == PLATFORM_WINDOWS){
// TODO: Write for Windows
}else{
System.out.println("OS not supported");
}
System.out.println("Executed command:");
System.out.println(strCommandLine);
executeCommandLine(strCommandLine);
}
NOTE: Coming back to this later as I've been unable to find a working solution. Draining the input streams manually instead of using BufferedReaders doesn't seem to help as the inputStream.read() method permanently blocks the program. I placed the gpg call in a batch file, and called the batch file from Java to only get the same result. Once gpg is called with the decrypt option, the input stream seems to become inaccessible, blocking the entire program. I'll have to come back to this when I have more time to focus on the task. In the mean time, I'll have to get decryption working by some other means (probably BouncyCastle).
The last option to probably try is to call cmd.exe, and write the command through the input stream generated by that process...
I appreciate the assistance on this issue.
I've been working on this problem for a couple days and haven't made any progress, so I thought I'd turn to the exeprtise here for some help.
I am creating a simple program that will call GnuPG via a Java runtime process. It needs to be able to encrypt and decrypt files. Encryption works, but I'm having some problems decrypting files. Whenever I try to decrypt a file, the process hangs.exitValue() always throws it's IllegalThreadStateException and the program chugs along as if it's still waiting. The code for these methods is attached below. The ultimate goal of the program is to decrypt the file, and parse it's contents in Java.
I've tried three approaches to getting the gpgDecrypt method to work. The first approach involved removing the passphrase-fd option and writing the passphrase to gpg via the gpgOutput stream in the catch block, assuming it was prompting for the passphrase like it would via the command line. This didn't work, so I put the passphrase in a file and added the -passphrase-fd option. In this case, the program repeats infinitely. If I write anything via the gpgOutput stream the program will complete. The Exit value printed will have a value of 2, and the result variable will be blank.
The third option is BouncyCastle, but I'm having problems getting it to recognize my private key (which is probably a separate post all together).
The keys I'm using to encrypt and decrypt are 4096-bit RSA keys, generated by GnuPG. In both cases using the passphrase and the passphrase file, I've tried piping the output to a file via > myFile.txt, but it doesn't seem to make any difference.
Here are the gpgEncrypt, gpgDecrypt and getStreamText methods. I posted both since the encrypt works, and I can't see any glaring differences between how I'm executing and handling the process between the encrypt and decrypt methods. getStreamText just reads the contents of the streams and returns a string.
EDIT: Quick note, Windows environment. If I copy the decrypt command output, it works via the console just fine. So I know the command is valid.
public boolean gpgEncrypt(String file, String recipient, String outputFile){
boolean success = true;
StringBuilder gpgCommand = new StringBuilder("gpg --recipient \"");
gpgCommand.append(recipient).append("\" --output \"").append(outputFile).append("\" --yes --encrypt \"");
gpgCommand.append(file).append("\"");
System.out.println("ENCRYPT COMMAND: " + gpgCommand);
try {
Process gpgProcess = Runtime.getRuntime().exec(gpgCommand.toString());
BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));
boolean executing = true;
while(executing){
try{
int exitValue = gpgProcess.exitValue();
if(gpgErrorOutput.ready()){
String error = getStreamText(gpgErrorOutput);
System.err.println(error);
success = false;
break;
}else if(gpgOutput.ready()){
System.out.println(getStreamText(gpgOutput));
}
executing = false;
}catch(Exception e){
//The process is not yet ready to exit. Take a break and try again.
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
System.err.println("This thread has insomnia: " + e1.getMessage());
}
}
}
} catch (IOException e) {
System.err.println("Error running GPG via runtime: " + e.getMessage());
success = false;
}
return success;
}
public String gpgDecrypt(String file, String passphraseFile){
String result = null;
StringBuilder command = new StringBuilder("gpg --passphrase-fd 0 --decrypt \"");
command.append(file).append("\" 0<\"").append(passphraseFile).append("\"");
System.out.println("DECRYPT COMMAND: " + command.toString());
try {
Process gpgProcess = Runtime.getRuntime().exec(command.toString());
BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getErrorStream()));
BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));
boolean executing = true;
while(executing){
try{
if(gpgErrorOutput.ready()){
result = getStreamText(gpgErrorOutput);
System.err.println(result);
break;
}else if(gpgOutput.ready()){
result = getStreamText(gpgOutput);
}
int exitValue = gpgProcess.exitValue();
System.out.println("EXIT: " + exitValue);
executing = false;
}catch(IllegalThreadStateException e){
System.out.println("Not yet ready. Stream status: " + gpgOutput.ready() + ", error: " + gpgErrorOutput.ready());
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
System.err.println("This thread has insomnia: " + e1.getMessage());
}
}
}
} catch (IOException e) {
System.err.println("Unable to execute GPG decrypt command via command line: " + e.getMessage());
}
return result;
}
private String getStreamText(BufferedReader reader) throws IOException{
StringBuilder result = new StringBuilder();
try{
while(reader.ready()){
result.append(reader.readLine());
if(reader.ready()){
result.append("\n");
}
}
}catch(IOException ioe){
System.err.println("Error while reading the stream: " + ioe.getMessage());
throw ioe;
}
return result.toString();
}
I forget how you handle it in Java, there are 100 methods for that. But I was stuck with decrypt command itself, it was very helpful, though you didn't need all those quotes and if you wish to decrypt a large file, it goes like this:
gpg --passphrase-fd 0 --output yourfile.txt --decrypt /encryptedfile.txt.gpg/ 0</passwrdfile.txt
Have you tried to run that command from command-line, not from Java code?
There can be an issue with 'for your eyes only' option, when GnuPG will wait for console output.
This may or may not be the problem (in the decrypt function)
BufferedReader gpgOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(new InputStreamReader(gpgProcess.getInputStream()));
BufferedWriter gpgInput = new BufferedWriter(new OutputStreamWriter(gpgProcess.getOutputStream()));
You are wrapping the result of getInputStream twice. Obviously gpgErrorOutput should be wrapping the error stream, not the input stream.
I stumbled upon this thread today because I was having the exact same issue as far as the program hanging. Cameron's thread from above contains the solution, which is that you have to be draining the inputStream from your process. If you don't, the stream fills up and hangs. Simply adding
String line = null;
while ( (line = gpgOutput.readLine()) != null ) {
System.out.println(line);
}
Before checking the exitValue fixed it for me.
It worked for me when i replace the decrypt command with below command
gpg --output decrypted_file --batch --passphrase "passphrase goes here" --decrypt encrypted_file
int exitValue = gpgProcess.exitValue();
// it gives process has not exited exception
The following code works with GNUPG 2.1.X
public static boolean gpgEncrypt(String file, String recipient,
String outputFile) {
boolean success = true;
StringBuilder gpgCommand = new StringBuilder("gpg --recipient \"");
gpgCommand.append(recipient).append("\" --output \"")
.append(outputFile).append("\" --yes --encrypt \"");
gpgCommand.append(file).append("\"");
System.out.println("ENCRYPT COMMAND: " + gpgCommand);
try {
Process gpgProcess = Runtime.getRuntime().exec(
gpgCommand.toString());
BufferedReader gpgOutput = new BufferedReader(
new InputStreamReader(gpgProcess.getInputStream()));
BufferedWriter gpgInput = new BufferedWriter(
new OutputStreamWriter(gpgProcess.getOutputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(
new InputStreamReader(gpgProcess.getErrorStream()));
boolean executing = true;
while (executing) {
try {
int exitValue = gpgProcess.exitValue();
if (gpgErrorOutput.ready()) {
String error = getStreamText(gpgErrorOutput);
System.err.println(error);
success = false;
break;
} else if (gpgOutput.ready()) {
System.out.println(getStreamText(gpgOutput));
}
executing = false;
} catch (Exception e) {
// The process is not yet ready to exit. Take a break and
// try again.
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
System.err.println("This thread has insomnia: "
+ e1.getMessage());
}
}
}
} catch (IOException e) {
System.err.println("Error running GPG via runtime: "
+ e.getMessage());
success = false;
}
return success;
}
// gpg --pinentry-mode=loopback --passphrase "siv_test" -d -o
// "sample_enc_data_op.txt" "sample_enc_data_input.gpg"
public static String gpgDecrypt(String file, String passphrase,
String outputfile) {
String result = null;
StringBuilder command = new StringBuilder(
"gpg --pinentry-mode=loopback --passphrase \"");
command.append(passphrase).append("\" -d -o \"").append(outputfile)
.append("\" --yes \"").append(file)
.append("\"");
System.out.println("DECRYPT COMMAND: " + command.toString());
try {
Process gpgProcess = Runtime.getRuntime().exec(command.toString());
BufferedReader gpgOutput = new BufferedReader(
new InputStreamReader(gpgProcess.getInputStream()));
BufferedReader gpgErrorOutput = new BufferedReader(
new InputStreamReader(gpgProcess.getErrorStream()));
BufferedWriter gpgInput = new BufferedWriter(
new OutputStreamWriter(gpgProcess.getOutputStream()));
boolean executing = true;
while (executing) {
try {
if (gpgErrorOutput.ready()) {
result = getStreamText(gpgErrorOutput);
System.err.println(result);
break;
} else if (gpgOutput.ready()) {
result = getStreamText(gpgOutput);
}
String line = null;
while ((line = gpgOutput.readLine()) != null) {
System.out.println(line);
}
int exitValue = gpgProcess.exitValue();
System.out.println("EXIT: " + exitValue);
executing = false;
} catch (IllegalThreadStateException e) {
System.out.println("Not yet ready. Stream status: "
+ gpgOutput.ready() + ", error: "
+ gpgErrorOutput.ready());
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
System.err.println("This thread has insomnia: "
+ e1.getMessage());
}
}
}
} catch (IOException e) {
System.err
.println("Unable to execute GPG decrypt command via command line: "
+ e.getMessage());
}
return result;
}
private static String getStreamText(BufferedReader reader)
throws IOException {
StringBuilder result = new StringBuilder();
try {
while (reader.ready()) {
result.append(reader.readLine());
if (reader.ready()) {
result.append("\n");
}
}
} catch (IOException ioe) {
System.err.println("Error while reading the stream: "
+ ioe.getMessage());
throw ioe;
}
return result.toString();
}