Any BASH experts in here?
I have a very crude startup script made by using WEBMIN on my Raspberry Pi. It starts up BLYNK
Now if I type the command line….
java -jar /var/blynk/server-0.10.2.jar -dataFolder /var/blynk &
That ampersand on the end will ensure my terminal program prompt comes back to me once the program is started up!!!
However, if I put that (and a change of directory which is necessary) into Webmin for a startup script…
It works ok – but the Raspberry Pi terminal comes up for login – but then starts this script – and stays in it – i.e. no more prompt – hitting Control C brings it back but of course the program has stopped.
Update: Wrapping in parentheses helps…. with that, one can get the prompt back by simply hitting ENTER and the program keeps running – but really, that’s not the answer. I don’t understand why this happens after the prompt first appears where all other services seem to be up and running before then. See comments…
My questions for script wizards are:
1. What do I need to change so that this will indeed run in the background like all the other items that Webmin has created
2. What can I change to add a STOP function to this?
#!/bin/sh
### BEGIN INIT INFO
# Provides: Blynk
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 5
# Description:
### END INIT INFO
case “$1” in
‘start’)
cd /var/blynk
java -jar /var/blynk/server-0.10.2.jar -dataFolder /var/blynk &
;;
‘stop’)
;;
*)
echo “Usage: $0 { start | stop }”
;;
esac
exit 0
Looks like you have this licked, but beware, there are differences between shell and bash i.e. #!/bin/sh and #!/bin/bash
Also I think it is best to use ./command_name – that’s because (unlike in Windows), the current directory isn’t part of your path by default.
If the start is early in the boot sequence then the path might not even be set up at all, so I would recommend always using the full path in a script.
Hi,
maybe this will work:
$ nohup java -jar /var/blynk/server-0.10.2.jar -dataFolder /var/blynk &>/dev/null &
This should start it up and detach it from the terminal (and redirect any output to /dev/null).
Hope it helps,
Pedro
Yes indeed it does! That pretty much cracks it – put in perspective here’s the entire start/stop/restart script for Blynk which now seems to work. Thanks for the top Pedro.
#!/bin/bash
NAME=server-0.10.2.jar
ARGS=’-dataFolder /var/blynk’
WORKFOLDER=’/var/blynk’
####################################
# Do not edit below this point #
####################################
PROGRAM=/var/blynk/$NAME
PID_FILE=/var/blynk/$NAME.pid
if [ ! -f $PROGRAM ]
then
echo “$PROGRAM not found”
exit 1
fi
function GetPID {
PID=`ps aux | grep $1 | grep -v grep | awk ‘{ print($2) }’`
}
GetPID $NAME
case “$1” in
‘start’)
if [ -n “$PID” ] ; then
echo “$NAME is already running”;
else
cd $WORKFOLDER
nohup java -jar $PROGRAM $ARGS &>/dev/null &
# (java -jar $PROGRAM $ARGS &)
if [ $? -eq 0 ] ; then
GetPID $NAME
echo $PID > $PID_FILE
echo started;
fi
fi
;;
‘stop’)
if [ -n “$PID” ] ; then
/bin/kill $PID;
rm $PID_FILE
echo ‘stopped’;
else
echo “$NAME is not running”
fi
;;
‘restart’)
/bin/kill $PID;
rm $PID_FILE
cd $WORKFOLDER
nohup java -jar $PROGRAM $ARGS &>/dev/null &
# (java -jar $PROGRAM $ARGS &)
if [ $? -eq 0 ] ; then
GetPID $NAME
echo $PID > $PID_FILE
echo restarted;
else
echo Not restarted;
fi
;;
*)
echo “Usage: $0 { start | stop | restart}”
exit 1
;;
esac
exit 0
Let’s try that again (looks like angle brackets are interpreted as html tags). Here’s a full-context example (not tested, might need some debuggery):
———-
#!/bin/bash
NAME=’server-0.10.2.jar’
ARGS=’-dataFolder /var/blynk’
WORKFOLDER=’/var/blynk’
####################################
# Do not edit below this point #
####################################
PROGRAM=”/var/blynk/$NAME”
PID_FILE=”/var/blynk/$NAME.pid”
if [ ! -f $PROGRAM ]; then
echo “$PROGRAM not found”
exit 1
fi
[ -f “$PID_FILE” ] && PID=”$(<$PID_FILE)”
case “$1” in
‘start’)
if [ -n “$PID” ]; then
echo “$NAME is already running”
else
( cd $WORKFOLDER ; /usr/bin/java -jar $PROGRAM $ARGS ) &
PID=$!
echo “$PID” > “$PID_FILE”
echo ‘started’;
fi
;;
‘stop’)
if [ -n “$PID” ]; then
/bin/kill -15 $PID
rm -f “$PID_FILE”
echo ‘stopped’
else
echo “$NAME is not running”
fi
;;
‘restart’)
[ -n “$PID” ] && /bin/kill -15 $PID
( cd $WORKFOLDER ; /usr/bin/java -jar $PROGRAM $ARGS ) &
PID=$!
echo “$PID” > “$PID_FILE”
echo ‘restarted’
;;
*)
echo “Usage: $0 { start | stop | restart}”
exit 1
;;
esac
exit 0
———-
Here’s a full example in context:
“`
#!/bin/bash
NAME=server-0.10.2.jar
ARGS=’-dataFolder /var/blynk’
WORKFOLDER=’/var/blynk’
####################################
# Do not edit below this point #
####################################
PROGRAM=/var/blynk/$NAME
PID_FILE=/var/blynk/$NAME.pid
if [ ! -f $PROGRAM ]
then
echo “$PROGRAM not found”
exit 1
fi
[ -f “$PID_FILE” ] && PID=”$( $PID_FILE
echo ‘started’
fi
;;
‘stop’)
if [ -n “$PID” ] ; then
/bin/kill -15 $PID
rm -f $PID_FILE
echo ‘stopped’
else
echo “$NAME is not running”
fi
;;
‘restart’)
[ -n “$PID” ] && /bin/kill -15 $PID
( cd $WORKFOLDER ; /usr/bin/java -jar $PROGRAM $ARGS ) &
PID=$!
echo “$PID” > $PID_FILE
echo ‘restarted’
;;
*)
echo “Usage: $0 { start | stop | restart}”
exit 1
;;
esac
exit 0
“`
For part 1, there are a few simple ways to get the behavior you’re looking for. The simplest is to just wrap the whole sequence in parens so all commands inside are executed in a subshell. This works as long as you’re not expecting anything in the current shell env to be modified by the commands. Your example was backgrounding already, and you didn’t mention doing anything with the results afterward, so give this a shot first:
“`
( pushd /some/path ; ./script.sh –arrrg ; popd; ) &
“`
If that won’t work, there are more things to try.
Hi Ian – it wasn’t backgrounding – that’s the problem. so if i disable it – all works well on reboot (but no BLYNK) and the command prompt appears on the PI. If I enable that script – I would have expected the same – but what was ACTUALLY happening was that the prompt was appearing – seconds later the starup message for BLYNK would appear and the prompt was no longer available without hitting control-C – I thought the point of the ampersand on the end was to avoid that.
Peter,
This is what i usually use as the basis for my startups when working on Debian based system
https://orrsella.com/2014/11/06/initd-and-start-scripts-for-scala-java-server-apps/
Craig
I’m at work and don’t have access to my Pi right now. But see if your system has a command called
start-stop-daemon
. This is what a lot of init scripts on my Ubuntu system use.For that matter, look at the other scripts in
/etc/init.d
for examples?Yes.. I’m having a little difficulty with that one….
Hi Pete,
Instead of
java -jar $PROGRAM $ARGS &
try
(java -jar $PROGRAM $ARGS &) &
Help me out here – did you mean for that ) or did you just mean 2 ampersands?
Exactly as written; i.e. your original line including the ampersand all enclosed in parentheses, with another ampersand at the end of the line.
A second ampersand here failed – produced a red “failed” message at the prompt
cd $WORKFOLDER
java -jar $PROGRAM $ARGS & &
This version
cd $WORKFOLDER
(java -jar $PROGRAM $ARGS) &
i.e. adding parentheses made some difference, the prompt was still missing, but simply hitting ENTER brought it back and the service continued to run.
Neither of these can be right – services don’t normally have such an interaction at the command line?
Both of those are not quite right – what you need is:
cd $WORKFOLDER
(java -jar $PROGRAM $ARGS &) &
Hi this is what I tried (I’m hoping my changes to wordpress will stop this messing up)
else
cd $WORKFOLDER
(java -jar $PROGRAM $ARGS &) &
if [ $? -eq 0 ] ; then
So the two lines in the middle there are as suggested.
The result..
[FAIL[startpar: service(s) returned failure: Blynk … failed!
Pete, do you really need to press control+c, or pressing Enter would suffice? Sometimes tasks that were put in background continue to send messages to the terminal, without blocking it. In this case, you could get a new prompt line simply pressing Enter. That being the case, you can also avoid completely the unwanted messages in your terminal by adding ‘> /dev/null’ before the & on your script.
No, enter just ends up with a blank line.. you have to hit Control-C to get out of it and that stops it running – all the hallmarks of a foreground process – yet the same thing done at the command line works!!
This is the script I use to start and stop a java program on Ubuntu.
It’s by no means as good as could be. Just as good as needed to be.
#!/bin/bash
NAME=JLogArchive.jar
ARGS=’-p 2400 -t 1000 -d /var/log/tc65/csv/’
####################################
# Do not edit below this point #
####################################
PROGRAM=/usr/local/bin/$NAME
PID_FILE=/var/run/$NAME.pid
if [ ! -f $PROGRAM ]
then
echo “$PROGRAM not found”
exit 1
fi
function GetPID {
PID=`ps aux | grep $1 | grep -v grep | awk ‘{ print($2) }’`
}
GetPID $NAME
case “$1” in
‘start’)
if [ -n “$PID” ] ; then
echo “$NAME is already running”;
else
java -jar $PROGRAM $ARGS &
if [ $? -eq 0 ] ; then
GetPID $NAME
echo $PID > $PID_FILE
echo started;
fi
fi
;;
‘stop’)
if [ -n “$PID” ] ; then
/bin/kill $PID;
rm $PID_FILE
echo ‘stopped’;
else
echo “$NAME is not running”
fi
;;
‘restart’)
/bin/kill $PID;
rm $PID_FILE
java -jar $PROGRAM $ARGS &
if [ $? -eq 0 ] ; then
GetPID $NAME
echo $PID > $PID_FILE
echo restarted;
else
echo Not restarted;
fi
;;
*)
echo “Usage: $0 { start | stop | restart}”
exit 1
;;
esac
exit 0
This looks good Johan.. but… where you have the line “java -jar $PROGRAM $ARGS &”
Can I prefix that line with “cd /var/blynk” ??? or “cd $CHANGEDIR” or similar?
Could you please send that in a plain email to pete @ scargill . org
WordPress has made a complete mess of the quotes and I don’t want to get experimental – thanks.
Ok I think I’ve turned off that smart quote nonsense. Here is my variation of your script Johan
#!/bin/bash
NAME=server-0.10.2.jar
ARGS=’-dataFolder /var/blynk’
WORKFOLDER=’/var/blynk’
####################################
# Do not edit below this point #
####################################
PROGRAM=/var/blynk/$NAME
PID_FILE=/var/blynk/$NAME.pid
if [ ! -f $PROGRAM ]
then
echo “$PROGRAM not found”
exit 1
fi
function GetPID {
PID=`ps aux | grep $1 | grep -v grep | awk ‘{ print($2) }’`
}
GetPID $NAME
case “$1” in
‘start’)
if [ -n “$PID” ] ; then
echo “$NAME is already running”;
else
cd $WORKFOLDER
java -jar $PROGRAM $ARGS &
if [ $? -eq 0 ] ; then
GetPID $NAME
echo $PID > $PID_FILE
echo started;
fi
fi
;;
‘stop’)
if [ -n “$PID” ] ; then
/bin/kill $PID;
rm $PID_FILE
echo ‘stopped’;
else
echo “$NAME is not running”
fi
;;
‘restart’)
/bin/kill $PID;
rm $PID_FILE
java -jar $PROGRAM $ARGS &
if [ $? -eq 0 ] ; then
GetPID $NAME
echo $PID > $PID_FILE
echo restarted;
else
echo Not restarted;
fi
;;
*)
echo “Usage: $0 { start | stop | restart}”
exit 1
;;
esac
exit 0
The problem is – when I reboot the Pi, I can see everything booting up – then the prompt comes up – and then a few seconds later….. “Blynk server successfully started…” – and the prompt disappears… I haveto hit control-C to get out of it… it’s STILL doing it…
There’s no need for ps to get the pid of a backgrounded command, just hang onto it after it’s executed:
“`
java -jar $PROGRAM $ARGS &
PID=#!
“`