1

Have already --make-pidfile in start-stop-daemon, but still couldn't see pid file being created. Anybody can help why?

#!/bin/bash
### BEGIN INIT INFO
# FIXME: set Provides and Short-Description
# Provides:          echobridge
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: initscript for echobridge
### END INIT INFO
# FIXME: your name here
# Author: Leonid Shevtsov <leonid@shevtsov.me>
# Do NOT "set -e"
PATH=/sbin:/usr/sbin:/bin:/usr/bin
# FIXME: configure your app here
DESC="home automation phillips hue emulator"
NAME="echobridge"
CWD=/home/pi/EchoBridge
DATA=/home/pi/EchoBridge/data
#IP=128.168.1.40
#PORT=80
USER=pi
GROUP=pi
JAVA="/usr/bin/java"
JVM_ARGS="-Dconfig.file=$DATA/habridge.config"
JAR_PATH=/home/pi/EchoBridge/ha-bridge-3.2.1.jar
#JAR_PATH=/home/pi/EchoBridge/ha-bridge-3.1.0.jar
JAVA_ARGS="$JVM_ARGS -jar $JAR_PATH"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
# Test that Java is installed
if [ ! -x "$JAVA" ]; then
  echo "Java executable not found at $JAVA"
  exit 2
fi
# Test that the application jar is present
if [ ! -r "$JAR_PATH" ]; then
  echo "Application JAR not found at $JAR_PATH"
  exit 2
fi
#
# Function that starts the daemon/service
#
do_start()
{
  # Return
  #   0 if daemon has been started
  #   1 if daemon was already running
  #   2 if daemon could not be started
  start-stop-daemon --start \
    --quiet \
   # --name $NAME \
    --make-pidfile \
    --pidfile $PIDFILE \
    --exec $JAVA \
    --test > /dev/null \
    || return 1
  # FIXME: export environment variables here
  # export PORT=8070
  start-stop-daemon --start \
    --quiet \
   # --name $NAME \
    --make-pidfile \
    --pidfile $PIDFILE \
   # --chuid $USER:$GROUP \
    --chdir $CWD \
    --background \
    --exec $JAVA \
    -- $JAVA_ARGS \
    || return 2
}
#
# Function that stops the daemon/service
#
do_stop()
{
  # Return
  #   0 if daemon has been stopped
  #   1 if daemon was already stopped
  #   2 if daemon could not be stopped
  #   other if a failure occurred
  start-stop-daemon --stop \
    --quiet \
   # --name $NAME \
    --pidfile $PIDFILE \
    --exec $JAVA \
    --retry=TERM/30/KILL/5
  RETVAL="$?"
  [ "$RETVAL" = 2 ] && return 2
  rm -f $PIDFILE
  return "$RETVAL"
}
#
# Function that checks if the daemon is running
#
do_status()
{
  start-stop-daemon \
    --start \
    --test \
    --oknodo \
    --pidfile $PIDFILE \
    --exec $JAVA
}
case "$1" in
  start)
  [ "$VERBOSE" != no ] && echo "Starting $DESC" "$NAME"
  do_start
  case "$?" in
    0|1) [ "$VERBOSE" != no ] && echo 0 ;;
    2) [ "$VERBOSE" != no ] && echo 1 ;;
  esac
  ;;
  stop)
  [ "$VERBOSE" != no ] && echo "Stopping $DESC" "$NAME"
  do_stop
  case "$?" in
    0|1) [ "$VERBOSE" != no ] && echo 0 ;;
    2) [ "$VERBOSE" != no ] && echo 1 ;;
  esac
  ;;
  status)
  do_status
  ;;
  restart|force-reload)
  echo "Restarting $DESC" "$NAME"
  do_stop
  case "$?" in
    0|1)
    do_start
    case "$?" in
      0) echo 0 ;;
      1) echo 1 ;; # Old process is still running
      *) echo 1 ;; # Failed to start
    esac
    ;;
    *)
    # Failed to stop
    echo 1
    ;;
  esac
  ;;
  *)
  echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
  exit 3
  ;;
esac***
0
 start-stop-daemon --start \
    --quiet \
   # --name $NAME \
    --make-pidfile \
    --pidfile $PIDFILE \
    --exec $JAVA \
    --test > /dev/null \

Comments in shell scripts do not work like that. You have made two commands,

 start-stop-daemon --start --quiet 
and

--make-pidfile --pidfile $PIDFILE --exec $JAVA --test > /dev/null 

Do not try to comment command arguments out that way.

For the onlookers who are despairing at the use of System 5 rc scripts and PID files, note that the first rule for migrating to systemd does indeed apply to the Philips Hue home automation bridge. In this particular case, one can find a service unit already written by BWS Systems for starters.

In the daemontools world, the run program for such a service is of course simple, especially as in your case where Java is straightforward /usr/bin/java. Here's one such:

#!/bin/nosh
setuidgid pi
userenv
chdir /home/pi/habridge
java -jar -Dconfig.file=data/habridge.config ./ha-bridge-3.2.2.jar

Of course, running the Java program non-superuser (as this run program does) means that it cannot bind a socket to port 80 as it wants to. This is why you've been trying to comment out the --chuid option in your System 5 rc script, no doubt.

In an ideal world, the Java program wouldn't be doing so, but rather one would be using something like tcp-socket-listen to bind a listening socket before running setuidgid to drop privileges and running the Java program, which would simply accept the listening socket as open file descriptor #3 without having to worry about any of this itself.

The idea that the service management system can do this for a service is common to the daemontools world, systemd, launchd, and even inetd. A daemontools run program (again using the nosh toolkit although one has a choice of toolkits for daemon management and for UCSPI) would look something like:

#!/bin/nosh
tcp-socket-listen --numeric-host --backlog 2 --bind-to-any 128.168.1.40 www-http
setuidgid pi
userenv
chdir /home/pi/habridge
java -jar -Dconfig.file=data/habridge.config ./ha-bridge-3.2.2.jar

Of course, many such Java programs apparently haven't caught up with the idea of being passed their communications sockets already opened. So one cannot run setuidgid before invoking Java here, and one has to trust yet another Java dæmon running with superuser privileges.

The reason that I mention this is that with daemontools-style run scripts interpreted by tools such as nosh and Laurent Bercot's execlineb, and with systemd's service units, one can comment things out in the way that you want to.

In a systemd service unit one could comment out the part that drops superuser privileges with .INI file comments:

;User=pi
;Group=pi
One would modify the first aforegiven run program as follows:

#!/bin/nosh
#setuidgid pi
#userenv
chdir /home/pi/habridge
java -jar -Dconfig.file=data/habridge.config ./ha-bridge-3.2.2.jar

  • You apparently can use CAP_NET_BIND_SERVICE instead of root with some tweaking: unix.stackexchange.com/questions/87978/… – dave_thompson_085 Nov 12 '16 at 14:49
  • That way you end up with a Java dæmon running with at least one privilege that it can freely abuse, when the goal is for it not to be running privileged at all; and also with all other Java programs invoked by the superuser having that same privilege. Have privileged code set up the socket, drop all privileges, and the Java program simply use the opened file descriptor, and one does not have either of those problems. – JdeBP Nov 14 '16 at 20:28
  • Except that I'm pretty sure standard Java doesn't do that, so you'll need (platform-dependent) JNI or maybe JNA. Remember Java runs on Windows which doesn't have file descriptors; instead it has file handles and socket handles which are not interchangeable. (And that OS doesn't restrict 'wellknown' ports to privileged processes in the first place, although the firewall can restrict to specified program(s).) – dave_thompson_085 Nov 15 '16 at 3:29
  • Yes, it does. It's java.io.FileDescriptor. The ideas that Java cannot handle environment variables and file descriptors, and so cannot implement these perfectly ordinary Unix and POSIX conventions that let dæmons interoperate with service managers and UCSPI, are a myth. (So, too, is the idea that sockets and files are distinct spaces on Windows. Your information about Windows has not caught up with Windows NT, or indeed StackOverflow. But your bringing up Windows is a red herring anyway. The questioner is using Linux and this is a Q&A about doing this on Linux.) – JdeBP Nov 15 '16 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.