java executing bash script, error=26 Text file busy - java

I've got a java code that is writing a Linux bash script out, then doing a chmod to add execute permission, then trying to execute it. I'm getting an IOException during the start of the process saying error=26, Text file busy. I've verified that the file is finished being written and the stream was closed. The chmod works fine, but I keep getting this error.
I've noticed that if I run a debugger and step through the code, it doesn't get the error, so clearly there is a timing issue involved. How can I make sure the chmod is done before I try to execute the bash script? I'd like to avoid non-reliable solutions like adding Thread.sleep(10000), and "hacky" things like putting the execution in a try/catch block inside a loop that tries until it succeeds.
I have a fair amount of code wrapping the startup of the process with listening threads, etc., but here is a simplified version of what it is doing (tried this code also and it has same result):
String[] cmd1 = {"/bin/chmod", "750", postFile };
new ProcessBuilder(cmd1).redirectErrorStream(true).start().waitFor();
String[] cmd2 = { postFile };
new ProcessBuilder(cmd2).redirectErrorStream(true).start().waitFor();
Every time after execution, the "postFile" has the correct 750 permissions, but it has not executed (due to the IOException).

For future reference, it may have been caused by an unclosed stream in this particular case, but setting permissions on a file immediately followed by running the file can cause this error too:
java.io.IOException: Cannot run program "...": error=26, Text file busy
It is a probable bug in JDK. In my case, it was caused by this snippet of code
Files.setPosixFilePermissions(Paths.get(scriptPath), set(PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.OWNER_READ));
ProcessBuilder processBuilder = new ProcessBuilder(scriptPath).directory(workingDir);
processBuilder.start();
even if nothing was editing the script file.

Are you sure it is the chmod that is responsible for the subsequent error? Could you check that you definitely close the output file before you try to run it?
If you do close it then I'm at a loss why chmod should cause that error, but you could avoid the need to run chmod by using your shell to run the script:
String[] cmd = {"bash", postfile };

I don't know if it's related but usually you need to get or redirect the ErrorStream and the InputStream (I usually get them in a ResponseStreamReader that I create, don't know about the redirecting choice).

In my service file in /etc/systemd/system/ I have directed outputs to log files:
StandardOutput=file:/home/pi/ApplicationLogs/application_l_debug.log
StandardError=file:/home/pi/ApplicationLogs/application_l_error.log
The error message disappeared when I changed permissions on the ApplicationLogs directory to write permissions to all
(chmod a+w ApplicationLogs)

Related

Waiting for batch process to finish before continuing with the rest of the codes in .java file

I have this java file, where I need to invoke a batch file from,
for this, I use the following line
Process proc = Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler "+ "D:\\Builds\\automation\\INSTALLER\\SOURCE\\A.bat");
This runs fine, the bat file is invoked in command prompt.
A.bat also has a few lines where 2 other bat files are called. You can consider them as B.bat & C.bat
After all these Batch files are run, there is a output.log file that is generated & has information if the process was "successful" or there were "errors". So based on the words in the log, I will need to either print "SUCCESS" or "ERROR".
Now, my problem is, I used
proc.waitFor();
so that the java file wait for the Process to finish before the remaining codes are run.
This just does not happen. Even before B.bat is run, "SUCCESS" gets printed.
Is there a way I could edit the batch file according to my needs or edit the java file to wait till the process completes?

bash scripting: search Java STDOUT for a variable

When I run myTest.jar, it outputs alot of information in STDOUT (not in a file) and I am trying to read/search that file for a specific string to put as a variable in my bash script.
java stdout:
line 1 info............
line 2 info...........
....
...
Successful (either 'Successful' or 'Failed')
How do I search for, in bash, the last line in the stdout or for ('Successful' or 'Failed') without redirecting the stdout to a file?
Thanks in advance
This is not a good way of checking for success or failure.
You should instead rewrite myTest.jar to use System.exit(0) on success and System.exit(1) (or higher) on error. If the program is well written, it will already do this.
You can then check for success or failure in bash using e.g.
if java -jar mytest.jar
then
echo "The command succeeded :D"
else
echo "The command failed :("
fi
All UNIX programs work this way, and you should make sure that myTest.jar is no exception.
To make this work, you would need to redirect stdout to a file and then cat/vim/search that file. Bash doesn't save the output of commands on its own.
Alternatively, you could use a program like screen that allows you to save a transcript of your session to a file. You would get the output of everything and the command lines though.
for future users, I used "that other guys' " method with some minor adjustments:
1) the exit code and what your doing have to be right after the running jar, wouldn't work for me in other segments
2) I read the exit code I was receiving and made an if loop for my conditions (0-2) exit code was given in java
3) piece of my bash code
EXIT_CODE=$?
echo Exit code: $EXIT_CODE
if [ $EXIT_CODE = "0" ]
then
...............do something
elif [$EXIT_CODE = "1"]
then
...............do something
else
...............do something
fi

How to run superuser commands on Linux through Java code?

My application has multiple users and 1 superuser. I am trying to write and store a file in Linux through Java code but i get permission denied error. I used the following code:
Process process = Runtime.getRuntime().exec("/usr/bin/tiff2pdf -o /tmp/tiff_dir/temp.pdf /tmp/tiff_dir/image.tiff");
int returnCode = process.waitFor();
I get following error:
java.io.FileNotFoundException: image.tiff (Permission denied)
From my analysis, it seems that because the user does not have root permissions, i am getting this error. What is the solution to this?
You shouldn't run a command like that as a super user because it poses a security risk (i.e. if someone gained control of your java program, then they have the keys to the kingdom). Instead, you should run with lower permissions.
It looks like the issue is with access to image.tiff not with tiff2pdf. Check the owner and permissions of image.tiff.
Firstly, these two lines will not produce a java.io.FileNotFoundException: image.tiff (Permission denied):
Process process = Runtime.getRuntime().exec("/usr/bin/tiff2pdf -o temp.pdf image.tiff");
int returnCode = process.waitFor();
If for some reason, the command fail, it will return a non-zero return code will produce some output on the process's standard error (that's the convention). You can get that standard error from process.getErrorStream() (it might be worth having a look at the standard output too, just in case). If there's an issue with the file not being found there, it will not throw a FileNotFoundException like this, since Java cannot understand the expected output from your command.
EDIT, following your comment:
It was thrown from this point only and value of returnCode was 1. Also everything worked fine once i manually changed the file permissions from a root user.
That's just not possible. If your application throws an exception at either of these two lines, it will exit the normal control flow: you will not be able to read the returnCode at all.
Secondly, your should run your exec command with each argument in a String[] instead of having it all in one line, this should prevent quotation problems if file names have spaces for example.
I would also suggest using absolute paths in your command, to make sure you're working in the directories you expect. (*EDIT: * Now that you're using absolute paths, make sure your user has rwx permissions on /tmp/tiff_dir .)
To answer your question more directly, you can certainly run sudo with Runtime.exec(new String[] {"/usr/bin/sudo", ... the rest of your command ... }, but this is a bad idea, for security reasons. You'd also need to change the sudoers file to allow it without password, or find a way to pass in a password, either on the command line (definitely a security risk!) or by passing it to the input stream manually, somehow.)
Try this :
File file = new File("/opt/image.tiff");
Runtime runtime = Runtime.getRuntime();
runtime.exec(new String[] { "/bin/chmod", "777",file.getPath()});
This will execute full permission on the file.

Executing python compiled script (.pyc) in Java

I have a python compiled script (script.pyc , I haven't the .py file)that work well from my windows command prompt, and I want to execute it from my Java's application.
I tried to use runtime() method :
Runtime runtime = Runtime.getRuntime();
runtime.exec(new String[] {"C:\\toto\\tools\\script.pyc" ,"arg","arg2" });
but I get an error :
Exception in thread "main" java.io.IOException: Cannot run program "C:\Nuance\VoCon Hybrid\SDK_v4_3\tools\clctodict.pyc": CreateProcess error=193, %1 n?est pas une application Win32 valid
The script work well in my terminal ("arg" is a txt file, "arg2" is the output name, and the script does its job without any problem).
I also try to launch my script with getDesktop() :
File fie = new File("C:\\toto\\tools\\script.pyc" ,"arg","arg2");
Desktop.getDesktop().open(fie);
There is no problem, but I can't add argument, so I can just see a terminal windows opening during a few second before disappearing instantly.
I have also tried to use JPython, without success too (maybe we can't use methode "execfile" on a .pyc????)
You can do something like
Process p = Runtime.getRuntime().exec(new String[]{"python.exe" ... other args)
Then you can invoke p.waitFor() to wait for the end of the process and p.exitValue() to test if the program exited successfully.
You can also get the output stream via p.getOutputStream() to retrieve the text printed by your python script
Please refer to the class documentation for further information : http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html
Just like you need a jvm to run a .class, you need a python interpreter to run a .pyc.
Try something like:
runtime.exec(new String[] {"c:\\Python26\\bin\\python.exe", "C:\\toto\\tools\\script.pyc" ,"arg","arg2" });

How can I execute a Java program within a php script?

I am writing a simple web upload script.
The goal is to upload a file using php, and then calling a java program to process this file.
I have done the work for uploading the file, but I cannot get a java program to be successfully run from within the php script.
I have tried exec(), shell_exec(), and system() with no results.
For the command, I have used "java Test", "java < directory >/Test", "/usr/bin/java < directory >/Test", I have even set up the application as a jar file with no results. The actual line of code I have used is:
echo shell_exec("java Test");
Usually there is no output. However, if I have just shell_exec("java"), then the last line of the help from java ("show splash screen with specified image") is displayed, which shows that the command has been executed. If I use, for example, shell_exec("whoami") I get "nobody" returned, which is correct. The only thing the java file does is create a file so that I can see that the application has been successfully run (the application runs successfully if I run it on the command line). I have set the permissions for the java file to 777 to rule out any possibility of permission errors. I have been struggling with this for a while trying all sorts of options with no results - the file is never created (the file is created with an absolute path so it's not being created and I just can't find the file). Does anyone have any ideas?
Thanks.
I have been struggling with this for a
while trying all sorts of options with
no results - the file is never created
(the file is created with an absolute
path so it's not being created and I
just can't find the file). Does anyone
have any ideas?
What I think the problem is. Apache runs as "nobody" group??(apache user??) which will execute the java script which will try to create a file on disc somewhere. I assume it does not have permission to write to that location. you should chown that folder so that apache user can write to that folder.
==
First off I would like to point out to you that calling exec() from a script could really blow up your server. I would advice you to use something like redis(see below) instead.
==
Second I think I know what the problem is. You should first try to run the simple example below which worked fine for me.
==
First be sure permission are set right. Because apache runs as nobody(most of the times).
I tried this simple test myself on ubuntu with php installed from repo.
test.java
class test {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
test.php
echo exec('java test');
Ran test.php
$ php test.php
Hello World!
==
Or you could try 1 of the following solutions(which would even be a better solution):
Write your java program as a webservice for example on top of atmosphere-spade-server(simple/embedded jar). This could be written insanely fast. But on high load this will not be best option I guess. Still I think this will be more than fast enough for you probably. Even this way it will be much faster as executing it, because you won't have the overhead running JVM. Could blow up your server, not as fast as exec()
Do a blocking pop/push from a redis(*nix) list structure. This will be pretty easy to write on *nux because there are client libraries for both java/php. The speed will best I guess because redis is written in C. I use redis myself.
Use a JMS like for example activemq. Also pretty easy to write because good library support. I have not used a JMS myself. I use redis solution. The speed I guess would be a little less then with redis solution.
I dont realy know, but i came a cross PHP-JAVA bridge maybe it can help
http://php-java-bridge.sourceforge.net/pjb/
Update:
I tested this with Jasper Reports, and it is working really nice. It will allow you to Extend Java classes with PHP or just use Java class lik it was PHP.
use java\lang\String as JString;
require_once("javabridge/java/Java.inc");
class String extends JString {
function toString () {
return "hello " . parent::toString();
}
}
$str = new String("Java");
echo $str->toString();
or
$temp = new Java('java.sql.Timestamp');
$javaObject = $temp->valueOf('2007-12-31 0:0:0');
$params = new Java("java.util.HashMap");
$params->put("text", "This is a test string");
$params->put("date",$javaObject);
More examples: http://php-java-bridge.sourceforge.net/pjb/FAQ.html
It's possible it has to do with the path that the exec is defaulting to. You may need to explicitly define your classpath with an absolute path to your .class or jar files when calling java.
<?php
$PATH="C:\Program Files\Java\jdk1.7.0_09\bin";
echo exec("javac theNameOfYourJavaProgram.java 2>&1");//shows # of errors
echo "<br />";
echo exec("java theNameOfYourJavaProgram 2>&1");//this line executes it
echo "<br />";
echo shell_exec("javac theNameOfYourJavaProgram.java 2>&1 ");//compiles it
?>

Categories

Resources