Running Jekyll from Java program under eclipse on OSX - java

I have a java program that does some preparation and then invokes Jekyll on the content it's prepared. Jekyll is a Ruby program installed on the local PC as a gem. On windows and linux, no problem, but when running on OSX, under the eclipse debugger, Jekyll doesn't run. Presumably this is because of interactive shell issues (Jekyll runs fine from the terminal).
Here's my java code:
DefaultExecutor exec = new DefaultExecutor(); // from org.apache.commons.exec
exec.setExitValue(0);
MyFilterHandler pumpHandler = new MyFilterHandler();
exec.setWorkingDirectory(new File("/Users/grahamegrieve/temp/igs/swissnoso/temp/pages"));
ProcessBuilder processBuilder = new ProcessBuilder(new String("bash -c jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output"));
Map<String, String> env = processBuilder.environment();
Map<String, String> vars = new HashMap<>();
vars.putAll(env);
String path = "/Users/grahamegrieve/.gem/ruby/3.1.0/bin:/Users/grahamegrieve/.gem/ruby/3.1.0/bin:/opt/homebrew/opt/ruby/bin:/Users/grahamegrieve/.nvm/versions/node/v17.4.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:"+env.get("PATH");
vars.put("PATH", path);
exec.execute(org.apache.commons.exec.CommandLine.parse("bash -c -i jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output"), vars);
this results in the following output from the process:
A subcommand is required.
followed by Jekyll's standard documentation - so Jekyll is running but not getting the parameters. The same thing happens in terminal:
➜ ~ bash -c jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output
A subcommand is required.
jekyll 4.2.1 -- Jekyll is a blog-aware, static site generator in Ruby
Usage:
jekyll <subcommand> [options]
In the terminal, I can do this:
➜ ~ bash -c 'jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output'
Configuration file: none
Source: /Users/grahamegrieve
Destination: /Users/grahamegrieve/temp/igs/swissnoso/output
Incremental build: disabled. Enable with --incremental
Generating...
so the parameters work fine when the entire command is wrapped in ''. But putting '' (or "") in the java code results in
Jekyll: bash: jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output: No such file or directory
As far as I can tell, that means there is no file with the name 'Jekyll build ...'.
So I don't know how to invoke Jekyll from my java code on OSX. Is it possible?

The answer is over here: execute shell command with org.apache.commons.exec.DefaultExecutor
It's to do with the way CommandLine works, and interacts with Bash.
DefaultExecutor exec = new DefaultExecutor(); // from org.apache.commons.exec
exec.setExitValue(0);
MyFilterHandler pumpHandler = new MyFilterHandler();
exec.setWorkingDirectory(new File("/Users/grahamegrieve/temp/igs/swissnoso/temp/pages"));
ProcessBuilder processBuilder = new ProcessBuilder(new String("bash -c jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output"));
Map<String, String> env = processBuilder.environment();
Map<String, String> vars = new HashMap<>();
vars.putAll(env);
String path = "/Users/grahamegrieve/.gem/ruby/3.1.0/bin:/Users/grahamegrieve/.gem/ruby/3.1.0/bin:/opt/homebrew/opt/ruby/bin:/Users/grahamegrieve/.nvm/versions/node/v17.4.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:"+env.get("PATH");
vars.put("PATH", path);
CommandLine cmd = new CommandLine("bash").addArgument("-c").addArgument("Jekyll build --destination /Users/grahamegrieve/temp/igs/swissnoso/output", false);
exec.execute(cmd, vars);

Related

Java Spring Boot failing to find Python Script in resources folder

I am trying to call python Scripts(in resources) from my Java class.
This is my code spinnet
String res = "/Scripts/Brokers/__init__.py";
URL pathUrl = this.getClass().getResource(res);
String path = "";
if(pathUrl != null)
path = pathUrl.toString();
ProcessBuilder pb = new ProcessBuilder("/usr/bin/python3.6", path);
ProcessBuilder is giving error No such file or directory.
P.S.
value of path = "file:/home/path-to-project/project-name/out/production/resources/Scripts/Brokers/\__init__.py"
Also how to include python scripts in jar file to run the project on linux server.
I am stuck with this issue since last 3 days. Please suggest.
From java doc:
https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
Starting a new process which uses the default working directory and
environment is easy:
Process p = new ProcessBuilder("myCommand", "myArg").start();
So basically, you going to fork a sub process that will
start a python interpreter
with the python script that you have provided as argument.
The path to your script should be a normal path that your OS can understand, therefore you should not give a URI? like path (protocol:address/path).
if (path.contains(":"))
path = (path.split(":"))[1];
Also the backslash \ before __init__.py looks suspicious.
You should be able to run ls /home/path-to-project/project-name/out/production/resources/Scripts/Brokers/__init__.py and see the file, the same goes for ls /usr/bin/python3.6.

Unable to get Eclipse to recognize binaries using ProcessBuilder located on $PATH on mac os x

I have just switched over to working on a mac and I am trying to determine why I am unable to get Eclipse to recognize the binary I am trying to run via a ProcessBuilder.
I have tried to run it both as a Java Application in Eclipse and as a TestNG test.
If I compile the class with java and run it directly from the command line it will work but not through Eclipse which leads me to believe the configuration for the $PATH is not setup correctly in my TestNG configuration.
Question
I am sure this is a configuration issue within Eclipse but after searching for a day and coming up short I wanted to post for some help. I have tried to set $PATH on the configuration but it does not seem to work.
Thank you
Update /Answer
It turned out that the PATH I had set on the shell shown below was not the same that Java had which I checked using the code below. After verifying that I then added the proper path to my environment on the ProcessBuilder and executed the script as shown in the answer.
Map<String, String> env = processBuilder.environment();
for (String key : env.keySet())
System.out.println(key + ": " + env.get(key));
Map<String, String> envs = processBuilder.environment();
System.out.println("Path " + envs.get("PATH"));
envs.put("PATH", "/usr/local/bin");
System.out.println("PATH " + envs.get("PATH"));
Code
File logsDir = new File(logDirectory);
if (!logsDir.exists()) {
logsDir.mkdirs();
}
// run process directly
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("appium");
processBuilder.redirectError(new File(logsDir, "appiumError.txt"));
processBuilder.redirectOutput(new File(logsDir, "appiumOutput.txt"));
process = processBuilder.start();
Output (it cannot find node to run appium hence the No such file or directory)
Caused by: java.io.IOException: Cannot run program "appium": error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at AppiumService.startAppium(AppiumService.java:77)
Path (The bin for node and appium is in /usr/local/bin)
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:
/usr/local/opt/ant/bin:/usr/local/opt/maven/bin:
/usr/local/opt/gradle/bin
The PATH variable of the java-process might be explicitly set by Eclipse not containing the paths you need. You can call the command using the absolute path to the corresponding directory or you might try using a shell to start the process by creating the process with
processBuilder.command("/bin/sh", "-c", "appium");

Invoking PowerShell script as other user from inside Java

I've got a chain of scripts that work as expected when invoked from the command line, but if the same user is running TomCat as a service under the same account Start-Process appears to return without doing anything.
My question is, is there something inherently different the environment built during a command executed from Java? Any pointers would be helpful.
Invocation from Command Line
If I issue the command cmd /c c:\test\test.bat when logged in as cuser1 at a non-elevated command prompt, I see the following log:
HS0\cuser1 called script as HS0\cuser2
Script running as HS0\cuser2
Invocation from Java Process
If I issue the same command using Runtime.getRuntime().exec() from inside my TomCat application, I don't see the switch.
List<String> cmd = new ArrayList<>();
cmd.add("cmd");
cmd.add("/c");
cmd.add("C:\\test\\test.bat");
final Process process = Runtime.getRuntime().exec(cmd);
...
// Handling the command output, nothing in the output, no error result
Instead, I only see the first line of the log. I've been catching exceptions, looking at exceptions and reading the output of the command, but it appears that the Start-Process command returns immediately without an error code. This is obviously test code with hardcoded credentials and not the real deal, but I can see the same behavior in this simplified code.
The Test
c:\test\test.bat => calls a PowerShell script
c:\test\test-switch.ps1 => invokes a PowerShell script as different user
c:\test\test.ps1 => display current user
test.bat
PowerShell -NoProfile -ExecutionPolicy Bypass -File "c:\test\test-switch.ps1"
test-switch.ps1
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$pwd = ConvertTo-SecureString "password" -asplaintext -force
$cred = New-Object System.Management.Automation.PSCredential ("HS0\cuser2", $pwd)
$args = "-NoProfile -ExecutionPolicy Bypass -File c:\test\test.ps1"
Start-Process Powershell -Credential $cred -ArgumentList $args
"$currentUser called script as HS0\cuser2" | Out-File 'c:\test\test.log' -Append
test.ps1
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
"Script running at $(Get-Date) as $currentUser" | Out-File 'c:\test\test.log' -Append

Path change ActiveXObject not working

I am using ActiveXObject for some print jobs what I doing is placing java class file on Desktop and doing stuff as follows:
var shell = new ActiveXObject("WScript.Shell");
shell.run("cmd /c java HelloWorldPrinter1 \""+output+"\"");
It works fine.
I have moved my class file into C:\printjob
So I tried as follows:
var shell = new ActiveXObject("WScript.Shell");
shell.run("cmd /c C:/printjobjava/HelloWorldPrinter1 \""+output+"\"");
It is not working.
How can put path of a file correctly in ActiveXObject?
Have gone through various links but no use
I got the answer finally
shell.run("cmd /c java -cp C:\\printjob HelloWorldPrinter1 \""+output+"\"");

ProcessBuilder redirecting output

I am trying to redirect output of a process started with the help of ProcessBuilder using following code
ProcessBuilder pb = new ProcessBuilder("/myScript >> /myLogFile 2>&1 <& - &");
Map<String, String> env = pb.environment();
env.clear();
env.put("var1", "val1");
env.put("var2", "val2");
pb.redirectErrorStream(true);
Process p = pb.start();
But it failed with exception
Exception in thread "main"
java.io.IOException: Cannot run
program
"/myScript >>
/myLogFile
2>&1 <& - &": java.io.IOException:
error=2, No such file or directory at
java.lang.ProcessBuilder.start(ProcessBuilder.java:460)
It works fine when I just pass "/myScript"
Script is perl, any suggestions/coments on why it is failing?
I tried passing all of them as seperate arguments like new ProcessBuilder("/myScript",">>","/myLogFile"), it executes but it does not redirect to log file and also it does not take envVars.
Shell redirection operators are unknown to ProcessBuilder. Put your command in a shell script and execute it, as shown here. Alternatively, use bash -c, as shown here.
As you specified, from Java7 you can keep using ProcessBuilder with the only executable file as parameter and redirect/intercept its output stream, using redirectInput() redirectOutput() and redirectError() from ProcessBuilder class.

Categories

Resources