Run shell inside watch service in java - java

I want to run shell script inside watch service class to run the shell after new file add to folder.
Watch service is working perfectly but when I want to add Runtime.getRuntime().exec("home/user/test.sh"); I recived error.
I just add Runtime after this:
// Dequeueing events
Kind<?> kind = null;
for(WatchEvent<?> watchEvent : key.pollEvents()) {
// Get the type of the event
kind = watchEvent.kind();
if (OVERFLOW == kind) {
continue; //loop
} else if (ENTRY_CREATE == kind) {
// A new Path was created
Path newPath = ((WatchEvent<Path>) watchEvent).context();
// Output
System.out.println("New path created: " + newPath);
Runtime.getRuntime().exec("home/user/test.sh")
What I have to do?

I thing problems with running script have nothing to do with WatchService, since you don't post actual exception that is throws (that would help a lot) I can only guess what is wrong, so please check this:
Script doesn't have permission to execute (easily fixable by chmod +x path/to/script.sh) - in that case you would get IOException with message like Permission denied or similar
System cannot find your script, since you are using relative path (no / at the beginning of script name) in that case ether use full script name e.g. /home/user/foo/script.sh or use proper relative path ../foo/script.sh - you should check if script exists before running it via exec (How do I check if a file exists in Java?)
Beware that script may be called with working directory of running Java program - so you should pass newly created file path as parameter to script to make it independent of its location
I followed tutorial that you were using with code:
if (OVERFLOW == kind) {
continue; //loop
} else if (ENTRY_CREATE == kind) {
// A new Path was created
Path newPath = ((WatchEvent<Path>) watchEvent).context();
// Output
System.out.println("New path created: " + newPath);
Runtime.getRuntime().exec(new String[] { "/home/xxx/foo.sh", newPath.toString() });
}
and script:
#!/bin/bash
echo "FILE CREATED: $1" >> /home/xxx/watch_dir.log
and it worked without any errors.

Related

Java command through CMD not working in C#.NET

I'm trying to run a java command in cmd using C# to get some inputs for my program, the path for Java is set correctly, and I am able to run Java commands in the cmd without any trouble but when I tried it in C#, it's showing " 'java' is not recognized as an internal or external command, operable program or batch file. " as if the path is not set.
But I am able to run the same command outside, don't know what seems to be the issue, kindly help, thanks in advance!
string cmd = #"/c java -jar """ + $"{treeEditDistanceDataFolder}libs" + $#"\RTED_v1.1.jar"" -f ""{f1}"" ""{f2}"" -c 1 1 1 -s heavy --switch -m";
Console.WriteLine(cmd);
var proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = cmd;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.Start();
Console.WriteLine("Process started");
string output = proc.StandardOutput.ReadToEnd();
Console.WriteLine("Output was read");
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
This line is your problem:
proc.StartInfo.UseShellExecute = false;
When UseShellExecute is true, the system and user PATH variables will be used if the application to launch is just the executable name. Because you're setting it to false, and java doesn't exist in your application's folder, it isn't possible for .NET to find it.
You have two options:
Set UseShellExecute to true so that it can use the PATH variable to find java.
Use a fully qualified path, e.g. "C:\Program Files\Java\jdk1.8.0_101\bin\java"
See this answer for more info.

Recursive directory creation fails on device

My code runs in the simulator, but crashes on Android with a FileNotFoundException as it tries to FileSystemStorage#openOutputStream in an non-existing directory. I create all the needed directories recursively before using
private void ensureParentDirs(String file) {
final int j = file.lastIndexOf("/");
final String s = file.substring(0, j);
if (storage.isDirectory(s)) return;
storage.mkdir(s);
if (storage.isDirectory(s)) return;
ensureParentDirs(s);
storage.mkdir(s);
if (storage.isDirectory(s)) return;
Log.p("Cannot create directory: " + s);
}
which is supposed to work like new File(file).getParentFile().mkdirs(). It might be wrong, but then it shouldn't run in the simulator either, so I'd call it a bug.
I get the message
Cannot create directory:
file:///data/user/0/my.package.name/files//dump/000/abcd
but the parent directory ("000") has been successfully created. Using adb shell, I can create the directory using
mkdir /data/data/my.package.name/files/dump/000/abcd
so I can't see what's wrong. Any idea?
There was (possibly still existent) problem with double slashes. My path was
/dump/000/abcd
and I transformed it via
path -> APP_HOME_PATH + "/" + path
into
file:///data/user/0/my.package.name/files//dump/000/abcd
which failed because of the double slashes, while
dump/000/abcd
transforms into
file:///data/user/0/my.package.name/files/dump/000/abcd
and works correctly.

Strange error when deleting directory from Java: 0 bytes, access denied

I have written method that recursively deletes directory with its contents.
Code is executed on Windows - Eclipse - JVM7
Here's the code:
/**
* Empty and delete a folder with recursion.
*
* #param folder
* folder to empty
*/
public static boolean rmdir(final String folderPath, boolean deleteParent) {
File folder = new File(folderPath);
// check if folder file is a real folder
if (folder.isDirectory()) {
File[] list = folder.listFiles();
if (list != null) {
for (int i = 0; i < list.length; i++) {
File tmpF = list[i];
if (tmpF.isDirectory())
rmdir(tmpF.toString(), true);
tmpF.delete();
}
}
if (deleteParent && !folder.delete()) {
return false;
} else
return true;
}
return false;
}
When the code is executed no error is thrown, saying that directory has been deleted successfully.
When I open drive to confirm deletion, I can still see the folder which is now 0 bytes in size with "Access denied" error when trying to open it.
EDIT:
I am administrator, have all permissions and can R/W to this folder from Windows explorer (before Java breaks it).
My question is has anyone seen this before and what could be the cause of this??
One more thing:
It seems that the directory gets set to "DeleteOnExit" instead of "Delete" right away.
Because when program ends in Lotus Notes or Eclipse directory disappears.
Ok I got this resolved...
I was not Java issue, it was Lotus Notes/Domino issue.
Here comes the long sentence:
It seems when Lotus Notes/Domino thread creates folder "A" and some files in it using LotusScript mkdir, rmdir, and other IO methods and then executes Java VM which tries to delete folder "A" with all files in it, parent thread (Lotus Notes/Domino) gets corrupted and loses directory structure handle which results in error above.
Solution to the problem is simple Dir$() statement after Java finishes folder deletion.
When Dir$() is executed, phantom folder disappears.
Probably because the Dir$() call refreshes and releases whatever should be refreshed and released internally.
Java is probably not the best language to solve this problem in. You can do this with batch file programming in one line: rmdir <directory-to-completely-remove> /s /q. If you absolutely must do this in Java, then you can run this command from a Java program on windows with: Runtime.getRuntime().exec("cmd /C start /min cmd.exe /K \"rmdir <directory-to-remove> /s /q & exit\"");

Getting response from shell command to Java code

I'm using net.neoremind.sshxcute SSH Java API library to connect to a sftp server and execute a shell script present on that server.
My Shell Script does a simple job of moving files from that SFTP location to a HDFS location on some other machine.
Currently, there's no way to report if any of the files are not moved due to any reason such as connection failure, file with illegal name, empty file etc.
I wonder, how can I show that set of information for each failed file move from shell command back to Java code ?
This is my sample code :
// e.g sftpScriptPath => /abc/xyz
// sftpScriptCommand => sudo ./move.sh
// arguments => set of arguments to shell script.
task = new ExecShellScript(sftpScriptPath, sftpScriptCommand, arguments);
result = m_SshExec.exec(task);
if(result.isSuccess && result.rc == 0)
{
isSuccessful = true;
s_logger.info("Shell script executed successfully");
s_logger.info("Return code : " + result.rc);
s_logger.info("Sysout : " + result.sysout);
}
else
{
isSuccessful = false;
s_logger.info("Shell script execution failed");
s_logger.info("Return code : " + result.rc);
s_logger.info("Sysout : " + result.sysout);
}
The Result object returned from the exec method call includes:
exit status or return code (Result.rc),
standard output (stdout) (Result.sysout),
standard error (stderr) (Result.error_msg), and
an indication of success, based on return code and output (Result.isSuccess).
So, if you are committed to the current method of executing a shell script using the sshxcute framework, then the simplest way would be to have the move.sh script provide information about any failures while moving files. This could be done via a combination of return codes and standard output (stdout) and/or standard error (stderr) messages. Your Java code would then obtain this information from the returned Result object.

java code to search a file entire system, works fine on windows but infinite in linux ubuntu

Developing search utility to search a file entire computer system, works fine on windows platform but becomes an infinite process in ubuntu linux. Please help to overcome this flaw. The following is the main part of the code.
public static void fun(File f){ // root directory is passed as argument
try{
if(f.isDirectory()){
File [] fi=f.listFiles();
for(int i=0;i<fi.length;i++){
if(fileFound==true) break; // fileFound is boolean data type used as flag to indicate whether the file is found or not
System.out.println(fi[i].getName());
fun(fi[i]);
}
}
else{
if(f.getName().equalsIgnoreCase(txtFile.getText()) ||
(f.getName().toLowerCase().startsWith(txtFile.getText().toLowerCase())) ||
(f.getName().toLowerCase().endsWith(txtFile.getText().toLowerCase()))){
l.setText("file found " + f.getAbsolutePath()); // l is JLabel that indicated prints the info like file found and its path
fileFound=true;
}
}
}
catch(Exception e){
}
}
The error you are observing may be due to nested symbolic links.
The most effective approach to solve this problem would be to instead use FileUtils#iterateFiles from the excellent Apache Commons IO library.
There is something like "." (current directory) and ".." (above directory) in each dir in linux. Maybe thats your problem.
In unix like systems the first folder is "." (current folder)
and the second folder is ".." (the root folder)
you should skip the first 2 folders to avoid getting to the same folder over and over again.
try:
if(fi[i].getName() == "." || fi[i].getName() == "..")
continue;

Categories