Shell Using content of /usr/local/etc/javavms in an rc.d script

Okay, people were very kind in pointing me to how to find our which Java version is running by looking at the /usr/local/etc/javavms file here LINK. Now I have another question.

I have been working on an rc.d script that will manage a Java application here LINK. I now have that running. My questions is this.

Is there a way to use the output of /usr/local/etc/javavms in my rc.d script?

Code:
# $FreeBSD$
#
# PROVIDE: foobar
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf to enable foobar by using
# sysrc or by editing the file directly.
#
# foobar="YES"
#
# This script takes one of the following commands:
#
# start stop restart status
#

. /etc/rc.subr

: ${foobar_enable:="NO"}
: ${foobar_user="root"}
: ${foobar_args="-Xms512M -Xmx512M -classpath '/usr/local/apps/foobar.jar' com.foobar.Service"}

name=foobar
procname="/usr/local/openjdk8/jre/bin/java"
desc="Foobar Service"
rcvar="${name}_enable"
pidfile="/var/run/${name}.pid"
command="/usr/sbin/daemon"
stop_postcmd="echo Bye-bye"
command_args="-t ${name} -T ${name} -u ${foobar_user} -S -p ${pidfile} ${procname} ${foobar_args}"

load_rc_config "${name}"

run_rc_command "$1"

I am stuck trying to use the values from /usr/local/etc/javavms in the procname.

Why are you wanting to do this?, you might ask. Well, when I used /usr/local/bin/java in the procname, my application would not show status correctly...
Bash:
root@localhost:/usr/local/etc/rc.d # service foobar status
foobar is not running.
root@localhost:/usr/local/etc/rc.d #

However, when I used /usr/local/openjdk8/jre/bin/java, my application would show status correctly...

Bash:
root@localhost:/usr/local/etc/rc.d # service foobar status
foobar is running as pid 24360.
root@localhost:/usr/local/etc/rc.d #

Any ideas? It would be really nice to not have to hard-code the value in my rc.d script...
 
Please have a look at /etc/rc.subr and its function _find_processes(). I have similar problems starting a shell scrpt. Add some code as below.
Code:
_find_processes()
{
    logger "CBR _find_process start"
    logger "CBR _find_process rc_pid $rc_pid"
    if [ $# -ne 3 ]; then 
        err 3 'USAGE: _find_processes procname interpreter psargs'
    fi   
    _procname=$1
    _interpreter=$2
    _psargs=$3
    logger "CBR _procname $1 _interpreter $2 _psargs $3"

    _pref=
    if [ $_interpreter != "." ]; then   # an interpreted script
        logger "CBR _find_process interpreter != ."
        _script="${_chroot}${_chroot:+/}$_procname"
        if [ -r "$_script" ]; then 
            logger "CBR _find_process script $_script"
            read _interp < $_script # read interpreter name
            case "$_interp" in
            \#!*)
                _interp=${_interp#\#!}  # strip #!
                set -- $_interp
                case $1 in
                */bin/env)
                    shift   # drop env to get real name
                    ;;   
                esac 
                if [ $_interpreter != $1 ]; then 
                    warn "\$command_interpreter $_interpreter != $1"
                fi   
                ;;   
            *)   
                warn "no shebang line in $_script"
                set -- $_interpreter
                ;;   
            esac 
        else
            warn "cannot read shebang line from $_script"
            set -- $_interpreter
        fi
        _interp="$* $_procname"     # cleanup spaces, add _procname
        _interpbn=${1##*/}
        _fp_args='_argv'
        _fp_match='case "$_argv" in
            ${_interp}|"${_interp} "*|"[${_interpbn}]"|"${_interpbn}: ${_procname}"*)'
    else                    # a normal daemon
        logger "CBR _find_process interpreter == ."
        _procnamebn=${_procname##*/}
            logger "CBR $_procnamebn"
        _fp_args='_arg0 _argv'
        _fp_match='case "$_arg0" in
            $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
        #logger "CBR $_fp_match"
        #logger $_procname|$_procnamebn|$$_procname|$_procnamebn|${_procnamebn}_procnamebn}
        #logger "(${_procnamebn})"|"[${_procnamebn}]"
    fi

    logger "PS $PS _fp_args $_fp_args _psargs $_psargs npid $_npid_jid JID $JID _jid $_jid jid $jid"
    logger "$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"
    _proccheck="\
        $PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
        while read _npid _jid '"$_fp_args"'; do
            '"$_fp_match"'
                logger "JID: $JID _jid: $_jid";
                if [ "$JID" -eq "$_jid" ];
                then echo -n "$_pref$_npid";
                _pref=" ";
                logger "IF Matches";
                fi
                ;;
            esac
        done'

#   debug "in _find_processes: proccheck is ($_proccheck)."
    logger "CBR _find_process _procheck $_procheck"
    eval $_proccheck
    _pref=" "
    _jid=0
    jid=0
    logger "CBR _find_process _procheck $_procheck"
    logger "CBR _find_process rc_pid $rc_pid"
    logger "CBR _find_process end"
}
This my actual file with debug messages by logger(1) which appear in /var/log/messages. The last part of _find_process constucts a string which invokes ps. Please check $procname which is expected by that command. In case of shell scripts it must be /bin/sh. I plan to write a howtodo about this procedure.

I hope its helps.
Kind regards,
Christoph
 
What's often quite useful is to look at other ports that need to use Java to start a service. To see how it's done there, databases/puppetdb7 is probably a nice example to use.


Code:
: ${puppetdb_enable="NO"}
: ${puppetdb_args="services -c /usr/local/etc/puppetdb/conf.d"}
: ${puppetdb_java_home="/usr/local/openjdk11"}
: ${puppetdb_user="puppetdb"}
: ${puppetdb_group="puppetdb"}
: ${puppetdb_log_file="/var/log/puppetdb/puppetdb.log"}

pidfile="/var/run/puppetdb/puppetdb.pid"
command="/usr/sbin/daemon"
java_cmd="${puppetdb_java_home}/bin/java"
procname="${java_cmd}"
command_args="-p ${pidfile} ${java_cmd} ${puppetdb_java_opts} -Djava.security.egd=/dev/urandom -cp /usr/local/share/puppetdb/puppetdb.jar clojure.main -m puppetlabs.puppetdb.core  ${puppetdb_args} > ${puppetdb_log_file} 2>&1"

required_files="${java_cmd}"

This also allows you to 'overrule' the java version through a rc.conf variable. Note that the -p ${pidfile} is an argument for daemon(8), not an argument for java(1).
 
Back
Top