netbeans java check if local services is running progammingly - java

I have n Netbeans Java project that connects to the MYSQL, to read data from my database.
But the MYSQL services is not running, and I have to manually start it.
Can I start this service in my code?
Windows Services

This solution is specific to Windows and assumes that the MySQL service name is MySQL80 (as shown in your screenshot). To start the MySQL service if it is not running from Java in Windows:
Create a BAT file containing nothing but NET START MySQL80
Create a shortcut to that BAT file. In Windows File Explorer display the properties of that shortcut, click the Shortcut tab, click the Advanced... button, and check the Run as administrator box:
Run the Java application shown below which will:
Check the status of the MySQL80 service by parsing the output returned by the command sc query MySQL80. See method getServiceState() in the code below.
If the service is not running (because getServiceState() returned "STOPPED"), run the shortcut to the BAT file (as an administrator) to start the service. See method startService() in the code below, and set your value of String shortcut as appropriate.
If the service is already running (getServiceState() returned "RUNNING"), or the service name is not recognized, the code does nothing.
If there is a problem starting the service the error stream is displayed.
This is the code:
package servicestarter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ServiceStarter {
public static void main(String[] args) {
try {
ServiceStarter ss = new ServiceStarter();
String serviceName = "MySQL80";
String serviceStatus = ss.getServiceState(serviceName);
if ("STOPPED".equals(serviceStatus)) {
System.out.println("Service " + serviceName + " is stopped. Starting the service...");
String shortcut = "D:\\temp\\netstartmysql80.bat.lnk";
Process process = ss.startService(shortcut);
// Display any error output. Should be nothing there if all goes well...
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
private String getServiceState(String serviceName) throws IOException {
String state = "";
Process process = Runtime.getRuntime().exec("cmd.exe /c sc query " + serviceName);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("STATE")) {
String[] tokens = line.split("\\s+");
state = tokens[tokens.length - 1];
break;
}
}
reader.close();
return state; // Returns "STOPPED" or "RUNNING", or empty string for invalid service name.
}
private Process startService(String shortcut) throws IOException {
return Runtime.getRuntime().exec("cmd.exe /c " + shortcut);
}
}
Method getServiceState() just parses the content produced by sc query MySQL80 to determine the status ("STATE") of the service:
C:\WINDOWS\system32>sc query MySQL80
SERVICE_NAME: MySQL80
TYPE : 10 WIN32_OWN_PROCESS
STATE : 1 STOPPED
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
Notes:
The above code works for me on Windows 10 starting a MySQL 8.0 service named "MySQL80", though it should start any STOPPED service by changing the value of String serviceName, and the name and content of the shortcut that is run.
This approach has a problem which may be a deal breaker: because the service must be started as an administrator you will normally get that familiar prompt from User Account Control when the shortcut to the BAT file is run, asking "Do you want to allow this app to make changes to your device?". You can easily avoid that prompt by running the application from a Command Prompt window that was Run as administrator, but that may not necessarily be a viable approach for you.
This is not a robust solution. If the output generated by SC QUERY {service name} changes this code may break, but I don't know of a Java API to query Windows services directly.

Related

Not receiving output from ProcessBuilder in YARN job

I have a Hadoop YARN cluster set up on some machines at my university (all machines running Linux Fedora 25). When running a mapreduce job in YARN, I am unable to receive the output from a call I make to a separate program. Interestingly, if I run my job locally (configured in mapred-site.xml), my method for calling the program and receiving its output works just fine. Below is my executeShellCommand class, which is instantiated and used in my first map task.
public class ExecuteShellCommand {
public String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
String [] args = command.split(" ");
String cmd = args[0];
ProcessBuilder pb = new ProcessBuilder().command(cmd, args[1], args[2], args[3], args[4], args[5], args[6], args[7]).directory(new File("path to executable"));
p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
p.waitFor();
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
return e.toString();
}
return output.toString();
}
}
Things I have made sure to check:
1) Permissions are appropriately set for all files/directories needed
2) Map tasks are run as current user (me), so no issues with illegal access
3) I am not receiving a file not found exception, so the path to the program I'm calling is correct
4) Checked the input/output stream for Process p (input stream set as java.lang.UNIXProcess$ProcessPipeInputStream#1000e80, output stream is null)
5) Instead of calling the program I need to use, I have tried a simple "echo" command, and could not receive that output either.
6) I have also tried using
p = Runtime.getRuntime().exec("myCommand")
but the results are the same (no output received)
As I already mentioned, when I run a job locally, my executeCommand method functions perfectly, and returns the output from the program I call. Only in YARN do the issues occur. I have a feeling that the problem caused by either not reading from the correct buffer, or the command issued to ProcessBuilder is never actually executed. I am quite stumped as to how to debug what is going on here, and any tips would be greatly appreciated!
After hours of trying all sorts of solutions, I figured out how to get the error stream from the process spawned with ProcessBuilder. Turns out when I set the working directory for the process, I forgot to update the path to one of the arguments I was passing it. D'oh!!!

Get instance of same Java application if it is already running

Is it possible to check if a Java application is already running and if it is, get an instance of it?
Say i have a jar that the first time it's clicked it opens a frame, and every time after that (until it's closed), it gets that frame and adds an object to it. This also needs to work without the main application having a close() method so the application will work again when reopened if it stops responding or it has been closed with task manager.
Java applications works on different process.
So is not so easy to interact between two different process (already running application and the new one).
What you can do is find a inter process communication mechanism and use it.
Typical inter process communications use files or a common database.
You can store the id of the current main thread executing your java app.
If a new process starts check if there is an already running application.
If yes, you can use the same (or a new one) inter process communication system to send information that the main process should update. Then the secondary process kill itself.
I know this is an old question, but I recently had to get count and PID of running instance in JAVA on Linux. Just thought I would post my solution in case it could help someone in the future. (I have been helped so much in the past, I figured I should pay back a little).
Switch return to lngPidOfrunning for PID of other instance rather than count.
public long checkIsAlreadyRunning(){
//Check if app is already running
long lngCountOfInstances = 0; //Use this to hold how many already running
String strProcessName = "appNameToCheckFor";
//If it is required to also capture app running from within NetBeans, remove the .jar
System.out.println("ps -ef|grep " + strProcessName);
try{
long lngPid = ProcessHandle.current().pid();//PID of this instance of the application
long lngPidOfRunning = 0; //Holder for PID of already running instance
System.out.println(lngPid+""); //Only for verification
Runtime rt = Runtime.getRuntime();
String[] cmd = {"/bin/sh", "-c", "ps -ef|grep " + strProcessName };
Process proc = rt.exec(cmd);
delay_ms(2);//found I needed small delay to ensure buffer was ready
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String strLineIn;
StringBuilder strOutput = new StringBuilder();
String strProcessId = "";
while ((strLineIn = reader.readLine()) != null) {
if(!strLineIn.contains("grep") && !strLineIn.contains(String.valueOf(lngPid))) {//ignore is PID is current, or line contais grep
strOutput.append(strLineIn + "\r\n");//Only here for debuging
lngCountOfInstances++;
}
}
reader.close(); //always close the reader
String strReturn = removeDuplicates(strOutput.toString()," "); // remove duplicate spaces frm reteun
String[] strArray = strReturn.split(" ");
if(strArray.length>2){lngPidOfRunning = isLong(strArray[1]);}//Aray index 1 will be PID, isLong checks if valid long and if yes, retunrs long, esle 0;
System.out.println(lngPidOfRunning + " --> " + strReturn); //Only here for debuging
}
catch(Exception ex){
ex.printStackTrace();
err(ex.getMessage(), ex); //remove this, I use funtion to log messages and stacktraces to file
}
//return lngPidOfrunning; //Use this is you would like to use the PID to bring running instance to front
return lngCountOfInstances; //use this if you just want to get count of running instances
}
private long isLong(String strValue){
if(NumberUtils.isParsable(strValue)){
return Long.parseLong(strValue);
}
return 0;
}

Why do I get a null returned when doing a bufferedReader.readLine(); in windows cmd and powershell?

I'm trying to make a java command line tool my team uses on our linux boxes run on our windows machines as well, however when the program prompts for input the bufferedReader.readLine() returns a null without a prompt.
The following runs as I would expect in linux and when running in my IntelliJ console, but not running in cmd or powershell.
public class CliTest {
public static void main(String[] args) throws Exception {
CliTest gen = new CliTest();
gen.run();
}
public void run(){
System.out.println("Hello World");
BufferedReader inputReader = new BufferedReader(new InputStreamReader(System.in));
try {
System.out.print("enter text: ");
String input = inputReader.readLine();
System.out.println("input: " + input);
} catch (IOException e) {
e.printStackTrace();
}
}
The class in being run/built using gradlew from the following bat script:
#rem
#rem run test
#rem
echo off
set LIB=atlib
set CP=%LIB%/*;%LIB%
.\gradlew.bat runCliTest
Gradle task:
task runCliTest(type:JavaExec) {
def argList = []
main = "com.example.CliTest"
args = argList
println(argList)
workingDir = rootDir
classpath = sourceSets.main.runtimeClasspath
}
This is what I would Expect to see:
Hello World
enter text: 1
input: 1
This is what I get:
Hello World
enter text: input: null
Based on the behavior that you have described, it is pretty clear that in the "cmd" and "powershell" cases, the "standard input" stream is at the end-of-stream position. Therefore, when readLine() is called, you get a null.
This is not surprising (to me) build tools don't normally take input on standard input. But it could also be something about the way you are running gradle.
Based on what I found here:
http://mrhaki.blogspot.com.au/2010/09/gradle-goodness-get-user-input-values.html
... it looks like you should be using System.console() to get hold of the Console object, and then using its methods to interact with the user. You need to allow for the console() method returning null if direct interaction with the user is not possible.

How to execute a interactive shell script using java Runtime?

I am wondering is there any way to execute following shell script, which waits for user input using java's Runtime class?
#!/bin/bash
echo "Please enter your name:"
read name
echo "Welcome $name"
I am using following java code to do this task but it just shows blank console.
public class TestShellScript {
public static void main(String[] args) {
File wd = new File("/mnt/client/");
System.out.println("Working Directory: " +wd);
Process proc = null;
try {
proc = Runtime.getRuntime().exec("sudo ./test.sh", null, wd);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Thing is when I execute above program, I believed it will execute a shell script and that shell script will wait for user input, but it just prints current directory and then exits. Is there any way to do this or it is not possible at all in java?
Thanks in advance
The reason it prints the current dir and exits is because your java app exits. You need to add a (threaded) listener to the input and error streams of your created process, and you'll probably want to add a printStream to the process's output stream
example:
proc = Runtime.getRuntime().exec(cmds);
PrintStream pw = new PrintStream(proc.getOutputStream());
FetcherListener fl = new FetcherListener() {
#Override
public void fetchedMore(byte[] buf, int start, int end) {
textOut.println(new String(buf, start, end - start));
}
#Override
public void fetchedAll(byte[] buf) {
}
};
IOUtils.loadDataASync(proc.getInputStream(), fl);
IOUtils.loadDataASync(proc.getErrorStream(), fl);
String home = System.getProperty("user.home");
//System.out.println("home: " + home);
String profile = IOUtils.loadTextFile(new File(home + "/.profile"));
pw.println(profile);
pw.flush();
To run this, you will need to download my sourceforge project: http://tus.sourceforge.net/ but hopefully the code snippet is instructive enough that you can just adapt to J2SE and whatever else you are using.
If you use a Java ProcessBuilder you should be able to get the Input, Error and Output streams of the Process you create.
These streams can be used to get information coming out of the process (like prompts for input) but they can also be written to to put information into the process directly too. For instance:
InputStream stdout = process.getInputStream ();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));
String line;
while(true){
line = reader.readLine();
//...
That'll get you the output from the process directly. I've not done it myself, but I'm pretty sure that process.getOutputStream() gives you something that can be written to directly to send input to the process.
The problem with running interactive programs, such as sudo, from Runtime.exec is that it attaches their stdin and stdout to pipes rather than the console device they need. You can make it work by redirecting the input and output to /dev/tty.
You can achieve the same behaviour using the new ProcessBuilder class, setting up the redirection using ProcessBuilder.Redirect.INHERIT.
Note sure at all you can send input to your script from Java. However I very strongly recommend to have a look at Commons Exec if you are to execute external scripts from Java:
Commons Exec homepage
Commons Exec API

Need to stop the user click the exe for the second time, while it is already running

I have developed a exe of my Java application, and run it from a thumb drive. It will take some time to execute. But my end user thinks it is not running and clicks for the second time. I need to stop this. I need to stop continuous click on the exe, while it is running. I used the shell script to check whether the exe is running or not. And displays the message, that the exe is already running. And stops the further process. I need this to be happened while exe is running for the second time. I couldn't figure this out. Is there any way to disable the exe from click, while it is running. Or how can I use the check whether it is running or not.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
public class VBSUtils {
private VBSUtils() { }
public static boolean isRunning(String process) {
boolean found = false;
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);
String vbs = "Set WshShell = WScript.CreateObject(\"WScript.Shell\")\n"
+ "Set locator = CreateObject(\"WbemScripting.SWbemLocator\")\n"
+ "Set service = locator.ConnectServer()\n"
+ "Set processes = service.ExecQuery _\n"
+ " (\"select * from Win32_Process where name='" + process +"'\")\n"
+ "For Each process in processes\n"
+ "wscript.echo process.Name \n"
+ "Next\n"
+ "Set WSHShell = Nothing\n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
line = input.readLine();
if (line != null) {
if (line.equals(process)) {
found = true;
}
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return found;
}
}
And In my main class, I called VBUtils.
boolean result = VBSUtils.isRunning("myexe.exe");
if(result)
{
msgBox("myexe is running. Please wait");
}
else
{
// my part of execution.
}
If I call like this, the exe got terminated. Both the first and second execution.
The easiest way would be to present the user with some kind of visual feedback, so he knows that the application is running. (e.g. a console window with messages, a wait dialog, ...)
You need to use some sort of flag to indicate that your app is running. Many apps use a temp .pid file. When your app starts it checks for a .pid file, if there is one then it exits with an error message. If there is no .pid file then it creates one and runs as normal.
First of all java has a provision for a very early splash screen:
http://download.oracle.com/javase/6/docs/api/java/awt/SplashScreen.html
Furthermore per RMI you can on startup connect to any possibly running instance and stop and transmit command line ("open files ..."). RMI allows you to play remote server.

Categories

Resources