I'm building a standalone application to run as a Linux (Ubuntu) daemon service, using Java. For that, I'm using the Java Service Wrapper lib.
During the execution of the service I'd like to be able to query for some status of the tasks executed by the application. In other words, I'd like to be able to print a custom message when I type on terminal:
service my-app status
Currently the message it prints is something like this:
My App is running: PID:1000, Wrapper:STARTED, Java:STARTED
I understand I need to use a more complex integration method (rather than the simplest one), but I couldn't find how to intercept the "status" call to print my own message.
How can I customize that message, using the Java Service Wrapper?
I got a half-solution. Inspecting the wrapper script code, as suggested by #Naytzyrhc, I found that the wrapper lib reads 3 files to create the status message:
bin/my-app.pid to print the PID of the running process;
bin/my-app.status to print the status of the wrapper itself;
bin/my-app.java.status to print the status of the wrapped application.
So, in the application code, to override the status message, just write the message in the my-app.java.status file.
There's only one gotcha: if the status message contains line breaks, the service my-app status doesn't print them, because it uses the echo command (as stated in this question Capturing multiple line output into a Bash variable). To solve this problem, just change the line from:
eval echo `gettext '$APP_LONG_NAME is running: PID:$pid, Wrapper:$STATUS, Java:$JAVASTATUS'`
to:
eval echo `gettext '$APP_LONG_NAME is running: PID:$pid, Wrapper:$STATUS, Java:"$JAVASTATUS"'`
(Using double quotes on $JAVASTATUS).
This is a half-solution because it doesn't fire an event to the running application, as I wanted. But it works for customizing the status message: it depends on the application how often the message is updated.
Related
In the context of a custom Rundeck plugin I am writing in Java, I need to make remote cli calls to scripts on node, and based on their output do an action.
Currently, I was able to capture the exit code of the execution only, and not the output text by calling:
NodeExecutorResult.getResultCode()
Is there a way to get the whole output?
My goal is to perform git push programatically rather then from a console window.
To this aim I create a process like:
val processbuilder=new ProcessBuilder(List("git.exe","push","origin","master").asJava)
process=processbuilder.start()
Now, the problem is that git.exe seems to start an other process, to the output/error and input of which I have no access. I know this because if I run it without internet connection, it just prints a message on the error output and quits, as it should. However if I do the same with having an internet connection, it prints nothing on its standard output/error. Also I cannot destroy the process in that case ( see : http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4770092 ), which is an indication that authentication takes place in a separate process that is created by git.exe and to which I have no access.
I tried to get around this by starting cmd.exe as a process and issue git push as a command, but also in this case writing the password to cmd.exe's standard input has no effect.
The platform I'm using is Windows 10 + Scala sbt.
What is the way out of this?
Edit:
I'm trying to do this from a JavaFX based Scala application rather than from a console Scala program.
Edit2:
Using the sys api here does not solve the problem. If you try to perform the gith push through sys api call, then two things can happen:
If there is no internet connection, it will print an error message on the gui application's console window ( it has one, if you run it with sbt run ).
It there is an internet connection then it will print nothing and you cannot perform the authentication. The process simply detaches and becomes unreachable for you.
The point is that git.exe seems to start a subprocess and you have no access to this subprocess. This is problem is special to Windows to which I gave a link in the question. When you run git in the Windows console window then it takes care of the sub processes input and output for you. You are however not in the same position as the operation system to do this.
I came up with a poor man's solution. It will run in a system console window but at least it can be started from the gui app.
The mixture that finally works is this:
1) Create a Windows batch file ( call it "temp.bat" ) which contains the command:
git push origin master
2) Start cmd.exe as a process and to its standard input write the following line:
start temp.bat
This will open a console window and initiate the git push. The authentication will be handled properly, you are prompted for the password and can type it in the console window.
Other versions don't work. For example 'start git.exe' won't open a new console window.
You can use Scala sys.process API.
import sys.process._
val statusCode = "git push origin master" ! // one ! for the statusCode
Or:
val commandOutput "git push origin master" !! // two ! for getting the output
I am trying to use the grinder load testing tool to reproduce the navigation recorded on a .har file using chrome dev tools.
I have generated this test script using har2grinder.
The script looks faily simple, just a bunch of get/post invocations and their headers.
I launch the grinder console:
java -classpath lib/grinder.jar net.grinder.Console
And then the agent processes, using this properties file:
java -classpath lib/grinder.jar net.grinder.Grinder grinder.properties
Then I start the whole thing from the console and all I can get is this output, showing 1000 errors on each of the 2 pages visited:
The web server (tomcat) log doesn't show any hits, and I don't see any grinder logs with any further details. How can I trace the problem?
Cant access the properties file :(
You need to look into the properties first and get the logs working ,
Please check grinder.logDirectory value , the logs will contain information .
Secondly check whether grinder.useConsole is set or not and the value of grinder.consolePort grinder.consoleHost have been edited to something other than default .Usually this change is not required.
Also set grinder.processes ,grinder.thread and grinder.run to 1 so that there is only one process with one thread and executes once will be easier to debug .
Next if you are NOT running against localhost then probably check that its not getting blocked across firewall since Grinder is really fast and can send many request in a small time .However these type of errors will get recorded in grinder logs and are very self explanatory.
I'm trying to make an web service which can also get commands via shell. So I want to make this app work like a daemon. So my question is how can I get arguments passed to shell while web service runs in the background? I can make script which starts this app as a daemon and give it a name but how can i get arguments in java passed later on?
EX. mydaemon add -stream somepage.com -channel channelName -start 2014-09-19 20:00:00 -end 2014-09-19 20:45:00
I can start a new thread in main method which gets system.in but will this get stuff sent to PID of my app. Btw, if this can make a change - I'm using Spring Boot in my app.
How to detect if java is run from cron or through interactive shell.
I need to determine if the script is called by a user (show error message in sys.out) or cron(send error as email)
In your your crontab job you can pass an additional command line switch like -Dcron=true and that you can check inside your java code to branch out your logic.
Normally the stdout and stderr of any job run by cron is sent to the owner of the cronjob in email already.
If you want to handle that explicitly just add a command line option such as --cron that is passed to the cron job. Or more generally --email=bob#whatever which allows any invocation to send its output via email.
I would support -D solution as a most portable.
Still, if you need to implement a no-configuration solution, and you're OK to limit yourself to specific flavour of Unix (e.g. Linux), you may walk process tree to find if any of your parents are cron process:
Under Linux, read /proc/self/status:
cat /proc/self/status
Name: bash
State: S (sleeping)
Tgid: 9872
Pid: 9872
PPid: 9870
...
Then, according to PPid entry above, read /proc/9870/status, ... and continue until you reach PPid 1, which is init. If cron nowhere to be found, you're not under cron.
I also pretty sure somewhere under /proc/self you can find a direct specification what console/tty the process is running under (if none, than it must be a daemon, started by cron or not), but I couldn't find it right away.