I have a program that is emulating a simple distributed file system. I need to be able to open a file locally using emacs in the terminal window to read or write. I am using Runtime.exec() on an String[] to represent the commands. If I use "emacs" I can get the machine I'm currently using to open an emacs window (this doesn't help for any other machines running the Client). However, I have been unable to resolve how to have emacs open within the terminal using this process. I've tried adding the parameter "-nw" but it does not seem to respond. This is what I'm currently trying to use:
boolean bool = execute("emacs", "-nw", cachedFile);
private boolean execute(String com, String id, String fileName) {
String[] commands = new String[3];
commands[0] = com;
commands[1] = id;
commands[2] = fileName;
try {
Process p = Runtime.getRuntime().exec(commands);
int blah = p.waitFor();
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}
If I drop the "-nw" then I can get only the machine that I'm working on locally to open a separate window for the GUI emacs. This is not helpful because I need other remote machines (that I'm connected thru with terminal) to be able to view or edit the file and X does not work since I'm not at those machines to see the new window.
I know for sure that "emacs -nw filename" is the proper command because if I manually type this into the terminal then it'll open emacs. However, I want the Runtime.exec() to manage this request.
Related
Is there anyway that a java application can read from an already open CMD window. For example, I've opened a cmd, ran "dir" and then decided to run my application, is there any way my application can read the information that's already in the open CMD window without opening another?
Thanks in advance
UPDATE:
My hope was that when one java application was ran, it would check any currently opened CMD windows to ensure that another one of my command-line applications hadn't been ran before it opened it itself.
Just spool the output of the executed command in a file.
For example : do dir > spool.txt
and from the java program open the spool.txt file with a FileInputStream.
To be sure that the content is totally written before reading it, you could for example :
use a marker in the written file to indicate it
check the modification date of the written file (if the modification date doesn't change during a defined period, it may be the signal that the writing is finished)
Update with updated question : checking whether a CMD windows is opened
UPDATE: My hope was that when one java application was ran, it would
check any currently opened CMD windows to ensure that another one of
my command-line applications hadn't been ran before it opened it
itself.
You could simply list the running processes of Windows by using the tasklist.exe program.
The information is retrieved with one line by process.
Then, check if one of the lines starts with cmd.exe.
If it is the case, it means a cmd.exe program is already running.
Here is a sample code ;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class CmdProcessSearch {
public static void main(String[] args) throws IOException {
boolean anyCmdProgramOpened = isAnyCmdProgramOpened();
System.out.println("isOpened = " + anyCmdProgramOpened);
}
public static boolean isAnyCmdProgramOpened() {
Process p;
try {
p = Runtime.getRuntime().exec(System.getenv("windir") + "\\system32\\" + "tasklist.exe");
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
if (line.startsWith("cmd.exe")) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
The C:\windows\system32 is usually in the PATH environment variable.
So, p = Runtime.getRuntime().exec("tasklist.exe"); should be enough
but to prevent any side effect or misconfiguration problem, specifying the absolute path is better.
New update with new comment : checking whether the Java application is running
I have used this code for a different section but if there is a cmd
window running, there is no guarantee that the user has used it to run
my program, package process;
In this case, if you can install jdk tools on the client machine you could check if is running a Java process using as main class, the main class of your application.
You could use jps (Java Virtual Machine Process Status Tool).
Here is the available options :
OPTIONS
The jps command supports a number of options that modify the
output of the command. These options are subject to change or removal
in the future.
-q
Suppress the output of the class name, JAR file name, and arguments passed to the main method, producing only a list of local VM
identifiers.
-m
Output the arguments passed to the main method. The output may be null for embedded JVMs.
-l
Output the full package name for the application's main class or the full path name to the application's JAR file.
-v
Output the arguments passed to the JVM.
-V
Output the arguments passed to the JVM through the flags file (the .hotspotrc file or the file specified by the -XX:Flags=
argument).
-Joption
Pass option to the java launcher called by jps. For example, -J-Xms48m sets the startup memory to 48 megabytes. It is a common convention for -J to pass options to the underlying VM executing
applications written in Java.
jps -l command that outputs the full package name for the application's main class or the full path name to the application's JAR file.
Here is a sample code by searching the main class of the application process.JavaProcessSearch :
package process;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class JavaProcessSearch {
public static void main(String[] args) throws IOException {
boolean isProcessRunning = isAJavaProcessWithMainClass("process.JavaProcessSearch");
System.out.println(isProcessRunning);
}
public static boolean isAJavaProcessWithMainClass(String mainClass) {
Process p;
try {
String javaHome = System.getenv("JAVA_HOME");
p = Runtime.getRuntime().exec(javaHome + File.separator + "bin/jps -l");
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
if (line.contains(mainClass)) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
If you cannot install jdk tools, you could store "somewhere" on the client machine, the process id of the application when it is started.
You can retrieve this information with the following method : ManagementFactory.getRuntimeMXBean().getName().
When it is not any longer running (stopped or crashed), you could remove this process id information.
When the application ia started, if a process id is retrieved on the client machine, you don't allow the application to start.
For stopped application case, shutdown hook should do the job.
For crashed application case, you could use a deamon thread that checks on a regular basis whether the application is always running by relying on the stored process id.
How can I set the focus (e.g. cmd+tab) of an arbitrary application (Java or not) from a Java program, on OSX?
Looking for an answer to this question, I came across this question, but it doesn't really help for OSX.
EDIT: one possibiltiy seems to be to use something like Quicksilver, and a Robot to send it keypresses with modifiers. I'd prefer something more portable, though, that requires less setup to make changes after it's compiled....
You should be able to reactivate an already running app using the open command that comes with OS X:
Runtime.exec("open /path/to/Whichever.app");
(Or some equivalent overload of that function.) This will also open an app if it's not running yet.
Chuck's answer tipped me off to osascript, so I decided to give it a shot straight from the command line. Managed to get it working with Runtime.exec(), osascript, and AppleScript.
Java launches an AppleScript and passes it the application name, using osascript from the command line, via Runtime.exec():
try {
List<String> shellCommandList = new ArrayList<String>();
shellCommandList.add("osascript");
shellCommandList.add("activateApplication.scpt");
shellCommandList.add(appName);
String[] shellCommand = (String[])shellCommandList.toArray(new String[0]);
Process p = Runtime.getRuntime().exec(shellCommand);
// if desired, pipe out the script's output
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String cmdOutStr = "";
while ((cmdOutStr = in.readLine()) != null) {
System.out.println(cmdOutStr);
}
// if desired, check the script's exit value
int exitValue = p.waitFor();
if (exitValue != 0) {
// TODO: error dialog
System.err.println("Invalid application name: "+ appName);
}
} catch (Exception e) {
e.printStackTrace();
}
And the AppleScript uses a run handler to capture the incoming argument:
on run (arguments)
set appName to (item 1 of arguments)
tell application appName to activate
return 0
end run
You can use the javax.script API to run AppleScripts. So you can write a script along the lines of "tell application "WhateverApp" to activate", filling in your arbitrary application for WhateverApp, and it should do what you want.
This is my first question on stackoverflow so I'll try to keep it concise and relevant.
I'm currently creating a Java program that is attempting to call an external program located on the system, in order to do this however I am required to call a shell script that sets up links to the relevant libraries to ensure that the system is linked to these before the external program can be executed.
The issue at hand is that I cannot invoke the shell script through Java, I've researched high and low and am aware that of alternative ways such as the use of the ProcessBuilder class. Unfortunately I'm quite new to the world of trying to invoke command line statements through Java and so I'm stuck for answers.
An example of the code I am using can be found below:
private void analyse_JButtonActionPerformed(java.awt.event.ActionEvent evt) {
// Get project path for copying of Fortran program to folder and execution
String projectPath = Newproject_GUI.getProjectPath();
String sourcePath [] = {"/bin/sh ", "-c ","source ~/set_env_WRF_gnu.sh"} ;
Runtime fortranAnalyser = Runtime.getRuntime();
try {
Process p = fortranAnalyser.exec("cp main.exe " + projectPath);
Process k = fortranAnalyser.exec(sourcePath);
BufferedReader is = new BufferedReader(new InputStreamReader(k.getInputStream()));
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
Logger.getLogger(Analyser_GUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
Process p works fine and does indeed copy main.exe to the intended directory when the method is called. Process k however does not and this is where the issue is.
Thanks in advance.
The issue is "source" is internal command of BASH (you are using "sh" but that is just BASH in the simplified mode). So what you do is:
you spawn new process "sh" and source something there (setting some VARIABLES I guess)
the process ends and all VARIABLES are lost
you spawn another process, but VARIABLES are already gone
I am not sure if you use those variables later on, but according to the script name it is probably setting some. Don't do that like this.
By the way if you only want to execute script in bash, you don't need to source it. To get it's side effects, just execute it with:
String sourcePath [] = {"/bin/sh ", "/home/XYZ/set_env_WRF_gnu.sh"} ;
Please note you cannot use ~ in this case, use Java to get your home dir.
I am unable to retrieve the output of "db2 list db directory" command in my Java program. Basically, what I am trying to do is this:-
A combo box is populated with db2 instances in the local system
User selects a particular instance from the combo box
A new Process is run to list the database for that instance
Display the database as another combo box
This is the piece of code I have done:-
// dbinstances is a Combo box (Eclipse SWT widget)
this.dbInstances.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent arg0) {
// get selected instance name
String instance = dbInstances.getText();
// command invokes db2 command window, sets current instance and issues list db command
String command = "db2cmd /c \"set DB2INSTANCE="+instance+" & db2 list db directory\"";
// execute command and read output
try{
Process p = Runtime.getRuntime().exec(command);
BufferedReader br= new BufferedReader(new InputStreamReader(p.getInputStream()));
String op = null;
while((op=br.readLine())!=null){
System.out.println(op);
}
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
public void widgetDefaultSelected(SelectionEvent arg0) {}
});
The problem is that the command executes, I am unable to retrieve the output. The window just opens and closes.
One solution I tried was to redirect the output to a temporary file and read it. It works, but is quite inefficient, since this piece of code runs each time the user selects an instance.
I am running DB2 9.7 Enterprise edition on Windows XP SP3 machine.
Any thoughts on how to retrieve the output in the Java program?
Thanks a lot in advance.
You can also use the DB2 API via JNI in order to retrieve the database list directory. You have to start the scan, get the entries, and then close the scan.
By doing this, you can control the db list in a better way that parsing an output that could variate by many reasons (HADR, the authentication mechanism, local or remote, with or without alias, ip address or server name, service name or port number, in linux (home dir) or in Windows (drive letter), and other things)
The DB2 API is the same in all platforms, so it is almost platform independent, you just have to know which library load (.so or .dll), but the rest is the same.
For more information take a look at:
db2DbDirOpenScan http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.api.doc/doc/r0001509.html
db2DbDirGetNextEntry http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.api.doc/doc/r0001492.html
db2DbDirCloseScan http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.api.doc/doc/r0001437.html
Ok, figured this one out. The required solution is to add /w and /i switches to the command :-
// command invokes db2 command window, sets current instance and issues list db command
String command = "db2cmd /c /w /i \"set DB2INSTANCE="+instance+" & db2 list db directory\"";
According to IBM developerWorks
// Additional information about db2cmd Options
-c Execute the DB2 command window and terminate.
-w Wait until the DB2 command window terminates.
-i Inherit the environment from the invoking shell.
-t Inherit the title from the invoking shell
I want to create a utility in Java to automate our building process. The current process involve
Opening 2 consoles for servers. ( I want to open these consoles from java program )
Running mulitple bat files in consoles and based on one batch file output, running other commands.
I need head start, what libraries should i use. Can i open 2 consoles from Java (independently). Like even if my program closes those consoles keep running. (consoles are bea server, startWebLogic.cmd).
Alee, yes you can do that with Runtime.getRuntime().exec("file.bat"); and then you have 2 options, you can capture the output of the execution
for example:
public static void main(String[] args) {
System.out.println("hello");
try {
Process p = Runtime.getRuntime().exec("./prog.sh");
InputStream in = p.getInputStream();
System.out.println("OUTPUT");
StringBuilder sb = new StringBuilder();
int c;
while( (c = in.read() ) > 0 ) {
sb.append((char) c);
}
//here the script finished
String output = sb.toString();
if( output.contains("Exception")) {
System.out.println("script failed");
}
if( p.exitValue() == 0) {
System.out.println("The script run without errors");
} else {
System.out.println("The script failed");
}
} catch (IOException e) {
e.printStackTrace();
}
}
this captures both scenarios, where you need to capture the output and then decide whether the script run successfully, or if you can use the exit status from the script.
The exitValue code is 0 for success and any other number for failure.
Surely you can open as many consoles as you want. If you wish to do it simultaneously creaete separate threads and then create process using Runtime.exec() or ProcessBuilder.
But why do you want to do this? There is a good old ant that is a build tool dedicated for such tasks. It supports everything and it is extendable using custom tasks.
Moreover if you suddenly remember that it is 2011 now, use newer tools like Apache Buildr.
Java's Runtime class has methods to launch Processes which have programmatic interfaces to their input/output streams and other management. However, I'm not sure how Windows handles processes whose parents have died.
You should also consider using the Windows Script Host via VB or JScript as you will probably have finer control.