I have a requirement where I need to execute 15 to 20 java programs parallely in the background. We can use nohup command and execute it directly but I want to execute this nohup command from another java program. I did some research on it and created a java program. but this below java program is working when I use java command, but if I use nohup then its failing
public static void main(String[] args) throws Exception {
String sourceFileName = args[0];
String targetFileName = args[1];
String type = args[2];
String logFileName = args[3];
Integer count = new Integer(args[4]);
// Below command is working
String command = "java -cp \"test-jar.jar\" com.test.MyTestClass ";
// Below command is not working
// String command = "nohup java -cp \"test-jar.jar\" com.test.MyTestClass ";
for(int i=1; i<=count; i++){
String cmd = command+sourceFileName+"_"+i+" "+targetFileName+"_"+i+" "+type+" 2>>"+logFileName+"_"+i+".log &";
runProcess(cmd);
}
}
private static void runProcess(String command) throws Exception {
Process pro = Runtime.getRuntime().exec(command);
pro.waitFor();
System.out.println(command + " exitValue() " + pro.exitValue());
}
For testing purpose I have taken the count as 3, If I use nohup command getting below output
nohup java -cp "test-jar.jar" com.test.MyTestClass source-file_1 target-file_1 TEST 2>>log-file_1.log & exitValue() 1
nohup java -cp "test-jar.jar" com.test.MyTestClass source-file_2 target-file_2 TEST 2>>log-file_2.log & exitValue() 1
nohup java -cp "test-jar.jar" com.test.MyTestClass source-file_3 target-file_3 TEST 2>>log-file_3.log & exitValue() 1
I kept the test-jar.jar in the same path from where I am executing this program.
Issue is because of 2 separate projects.
My class is in my-test project and the class which I want to execute is in test-jar project. I added test-jar dependency in 'my-test' project. Still faced the same issue. I added/copied My class in the test-jar file then I executed it. Now its working for both java and nohup commands
Related
I'm trying to do some automation on MacOS with Java.
no problems when running the commands manually from a terminal
i assume it works because of <user.home>/.zprofile
the commands are not found when trying to execute them via ProcessBuilder
How can I execute commands with the same environment as if running a zsh terminal manually?
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws Exception {
// these commands work
run("/bin/sh", "-c", "echo $PATH");
run("/bin/bash", "-c", "echo $PATH");
run("/bin/zsh", "-c", "echo $PATH");
// these commands all work when I run them manually in a terminal
// but fail here with "zsh:1: command not found: ..."
run("/bin/zsh", "-c", "node -v");
run("/bin/zsh", "-c", "npm -v");
}
private static void run(String... command) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.redirectErrorStream(true);
processBuilder.command(command);
Process process = processBuilder.start();
try(BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
for(String line = br.readLine(); line != null; line = br.readLine()) {
System.out.println(line);
}
}
System.out.println("return value: " + process.waitFor());
}
}
Output:
/usr/bin:/bin:/usr/sbin:/sbin
return value: 0
/usr/bin:/bin:/usr/sbin:/sbin
return value: 0
/usr/bin:/bin:/usr/sbin:/sbin
return value: 0
zsh:1: command not found: node
return value: 127
zsh:1: command not found: npm
return value: 127
After reading way too many articles about shells, and studying shell init diagrams, I decided to go with Zsh.
The reason was this blog post, which indicated that Zsh seems to have at least one init file that is executed for all possible shell variants (login, non-login, interactive, non-interactive etc).
I moved all my environment setup (PATH and LANG) to /etc/zshenv, deleted /etc/zprofile and all ~/.z* files.
I also changed the shell for both root and my user to Zsh (for the user this can also be done via system preferences):
dscl . -delete /Users/root UserShell && dscl . -create /Users/root UserShell /bin/zsh && dscl . -read /Users/root UserShell
dscl . -delete /Users/reto UserShell && dscl . -create /Users/reto UserShell /bin/zsh && dscl . -read /Users/reto UserShell
Now I get the same environment for:
SSH as root
SSH as user
Terminal.app
Processes started from Java
And pretty much everything else so far
So far so good. Test program output:
/usr/bin:/bin:/usr/sbin:/sbin
return value: 0
/usr/bin:/bin:/usr/sbin:/sbin
return value: 0
/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
return value: 0
v14.17.0
return value: 0
6.14.13
return value: 0
I'm using ProcessBuilder to run Postgres SQL scripts and my process seems to hang, because I'm not getting the exit value.
My code has a test method that loads and executes certain SQL files.
I then run some individual queries before executing the script file whose operations I want to test on.
#Test
public void test340() throws Exception {
String filePath = testFilePath; // Script file I want to test
TreeSet<Path> set = getFilePaths();
for (Path file : set) { // Run previous scripts to setup the db
loadFileAndExecuteSQL(file.toString());
}
preCondition340(); // Run some inserts
loadFileAndExecuteSQL(testFilePath); // Now load the script file I need to test
postCondition340(); // Run some other queries to verify resultset
}
public void loadFileAndExecuteSQL(String scriptFilePath) throws Exception {
String command = String.format("psql -v ON_ERROR_STOP=1 --host %s --port %s --dbname %s --file %s",
"localhost", "5432", dbName, scriptFilePath);
List<String> commands = Arrays.asList(command.split("\\s+"));
ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true);
final Process process = pb.start();
if(!process.waitFor(10000, TimeUnit.MILLISECONDS)) {
process.destroy();
}
System.out.println("Executing command " + command + process.exitValue());
}
The process seems to hang on my second call to loadFileAndExecuteSQL() Could anyone explain why this is happening and suggest how I can make sure this does not happen? Thanks.
I have a bash file:
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/bin/svnlook
LOGMSG=$($SVNLOOK log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]")
echo "\n$LOGMSG" >> /dev/tty
javac ~/Desktop/SomeClass.java
java ~/Desktop/SomeClass $LOGMSG
STATUS=$?
echo "\n" >> /dev/tty
echo $STATUS >> /dev/tty
exit 0
which calls this java file:
public class SomeClass {
public static void main(String[] args) {
String result = "";
for (String s: args) {
result = result + " " + s;
}
String regex = ".*\\bHello\\b.*";
if(result.matches(regex)) {
System.out.println("It matches");
System.exit(0);
} else {
System.out.println("It does not match");
System.exit(42);
}
}
}
I have never in the Java file have exited with the exit code of 1. However when I echo the status in the bash file, it always shows me '1' What can be the reason behind this?
The error code is because Java is failing to start. You aren't specifying the class to be run correctly.
If I have a class located in my desktop directory, I would need to use the following to run it from another directory:
java -cp ~/Desktop SomeClass
assuming that SomeClass has no package specified. If you have package org.foo.bar; at the top of the file, you would need to use
java -cp ~/Desktop org.foo.bar.SomeClass
I have a java application that downloads and runs another program. The problem I'm running into is that when it runs the program there is no visual; however, the process shows up in the Windows Task Manager.
Here's the relevant execution code:
String[] cmd = {System.getProperty("java.io.tmpdir") + PACKAGE_PATH + onePackage};
log.info("Package downloaded to: " + cmd[0]);
new ProcessBuilder(cmd[0]).start();
I've also used a Runtime.exec() and that produced the same results.
Here's a Commons Exec version that produces the same result:
String line = "cmd.exe start /c " + "\"" + cmd[0] + "\"";
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
One last bit of detail, it works fine on my Win7 desktop from Eclipse, but not on Windows Server 2008 R2.
You can do it with the following code:
import java.io.IOException;
public class TestClass {
public static void main(String[] args) throws IOException {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("cmd.exe /c mspaint.exe");
}
}
This will result in a mspaint.exe getting started up in the foreground compared to the background. However since you do it through cmd.exe that process ends immediately after mspaint.exe starts up resulting in the java program to finish its execution regardless of the status of the mspaint.exe which may be ok for your situation.
If you need to wait for it to finish, I would recommend looking at Commons Exec
I have a java program in which i have this code,
JOptionPane.showConfirmDialog(null, "TEST");
String pathToJar = ClassRewriter.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()+"ClassRewriter.class";
System.out.println(pathToJar);
ProcessBuilder pb = new ProcessBuilder("javaw "+pathToJar);
Process process = pb.start();
I have a java program in a class called classrewriter, and i am trying to start that program from within its main method but it doesnt seem to work.
public int runCommand(String command) throws Exception
{
Process s= Runtime.getRuntime().exec(command);
return s.exitValue();
}
So you write:
runCommand("java -jar "+pathToJar);
But it isn't recommend, because it isn't supported on all OSes (for example linux or mac).