Shell Custom rc.d script trouble

I am using an open source project (Traccar) and they provide a rc script to start and stop the service https://www.traccar.org/freebsd/

This script doesn't work, I can easily start the server if I do:

Code:
# cd /usr/local/traccar
# java -jar tracker-server.jar conf/traccar.xml &

However, I want to have this application handled by FreeBSD, so I wrote a custom rc.d script:

Code:
#!/bin/sh

## Service for traccar.

# PROVIDE: traccar
# REQUIRE: DAEMON
# BEFORE:
# KEYWORD: shutdown

# Add the following lines to /etc/rc.conf to enable `traccar':
#
# traccar_enable="YES"
#

. /etc/rc.subr

name="traccar"
rcvar=traccar_enable
pidfile_child="/var/run/${name}.pid"
pidfile="/var/run/${name}_daemon.pid"

traccar_chdir="/usr/local/traccar"


command="/usr/sbin/daemon"
start_precmd="${name}_prestart"
procname="traccar"

load_rc_config "$name"
: ${traccar_enable="NO"}
: ${traccar_root="/usr/local/traccar"}                    # standard root
: ${traccar_java="/usr/local/openjdk7-jre/bin/java"}    # path to your JRE
: ${traccar_user="root"}                        # user to run as
: ${traccar_stdout="/var/log/traccar_running.log"}
: ${traccar_stderr="/var/log/traccar_error.log"}

traccar_chdir=${traccar_root}                   # will add a cd $traccar_root before launching
command_args="-jar ${traccar_root}/tracker-server.jar ${traccar_root}/conf/traccar.xml"


traccar_prestart() {

    # set the daemon / java flags
    rc_flags="-r -P ${pidfile} -p ${pidfile_child} ${traccar_java} ${command_args} >> ${traccar_stdout} 2>&1 ${rc_flags}"
    #touch $pidfile
}

traccar_describe() {
    echo "Traccar started..."
}
run_rc_command "$1"

Now, this script starts the service, and correctly starts it when the machine is powered on.

However, it doesn't show as running...

Code:
# service traccar status
traccar is not running.

So I check the output of the PID files:

Code:
# cat /var/run/traccar.pid
50137
# cat /var/run/traccar_daemon.pid
49060

And if I can see those PID's here:

Code:
root@traccar:~ # ps aux
USER    PID %CPU %MEM     VSZ    RSS TT  STAT STARTED    TIME COMMAND
root  48997  0.0  0.0   10492   2444  -  IsJ  09:57   0:00.36 /usr/sbin/syslogd -s
root  49060  0.0  0.0   10468   2052  -  IsJ  09:57   0:00.00 daemon: /usr/local/openjdk7-jre/bin/java[50137] (daemon)
root  49103  0.0  0.0   20628   6260  -  SsJ  09:57   0:00.04 sendmail: accepting connections (sendmail)
smmsp 49114  0.0  0.0   20628   6072  -  IsJ  09:57   0:00.00 sendmail: Queue runner@00:30:00 for /var/spool/clientmqueue (sendmail)
root  49122  0.0  0.0   12592   2340  -  SsJ  09:57   0:00.01 /usr/sbin/cron -s
root  50137  0.0  1.3 4673476 418304  -  IJ   10:47   0:15.86 /usr/local/openjdk7-jre/bin/java -jar /usr/local/traccar/tracker-server.jar /usr/local/traccar/conf/traccar.xml -jar /usr/local/traccar/tracker-serv

And if I run kill on 50137 (the java process, which is also the same number returned from /var/run/traccar.pid) the deamon correctly brings it back up.

So my new script *half* works, it brings the application up, but doesn't show it as running from the service command, and because of this I cannot use

Code:
# service traccar restart
traccar not running? (check /var/run/traccar_daemon.pid)

Where as above, we know the PID returned from /var/run/traccar_daemon.pid is running and shows from ps output.

I think I am almost there, if anyone can help/advise what might be wrong, I would be very grateful, thanks.
 
Although you did provide a precmd and such I don't see where your script would perform the actual check. To my knowledge (from mind, it's been a while since I messed with this) that is handled by this statement:
Code:
run_rc_command "$1"
Which your script doesn't seem to use. Also see /etc/rc.subr for a full overview on all the pre-setup functions, as well as rc.subr(8). Pay specific note to check_pidfile() and _find_processes().

Still, skimming over rc.subr I think the real problem might be caused by the fact that your services don't match. Your service is called traccar but it's java which gets started and stopped.

If I then look at the rc file for Jenkins you'll see that it specifically anticipates for this:
Code:
pidfile=/var/run/jenkins/jenkins.pid
command=/usr/sbin/daemon
java_cmd="${jenkins_java_home}/bin/java"
procname="${java_cmd}"
And of course it's also using run_rc_command "$1" again at the end.
 
Although you did provide a precmd and such I don't see where your script would perform the actual check. To my knowledge (from mind, it's been a while since I messed with this) that is handled by this statement:
Code:
run_rc_command "$1"
Which your script doesn't seem to use.

Sorry, that was a copy & paste error, I have ammened my original post, the rc.d script does use it.

If I then look at the rc file for Jenkins you'll see that it specifically anticipates for this:
Code:
pidfile=/var/run/jenkins/jenkins.pid
command=/usr/sbin/daemon
java_cmd="${jenkins_java_home}/bin/java"
procname="${java_cmd}"
And of course it's also using run_rc_command "$1" again at the end.

That's a good reference point, so I modified my rc.d script to match the style of this:

Code:
#!/bin/sh -x

## Service for traccar.

# PROVIDE: traccar
# REQUIRE: DAEMON
# BEFORE:
# KEYWORD: shutdown

# Add the following lines to /etc/rc.conf to enable `traccar':
#
# traccar_enable="YES"
#

. /etc/rc.subr

name=traccar
desc="Traccar GPS tracking server"
rcvar=traccar_enable

load_rc_config "${name}"

load_rc_config "${name}"
: ${traccar_enable="NO"}
: ${traccar_root="/usr/local/traccar"}                    # standard root
: ${traccar_args="-jar ${traccar_root}/tracker-server.jar ${traccar_root}/conf/traccar.xml"}
: ${traccar_java="/usr/local/openjdk7-jre/bin/java"}    # path to your JRE
: ${traccar_user="root"}                        # user to run as
: ${traccar_stdout="/var/log/traccar_running.log"}
: ${traccar_stderr="/var/log/traccar_error.log"}

pidfile=/var/run/traccar.pid
command=/usr/sbin/daemon
java_cmd="${traccar_java}"
procname="${java_cmd}"
command_args="-p ${pidfile} ${java_cmd} ${traccar_args} >> ${traccar_stdout}"
required_files="${java_cmd}"
traccar_chdir=${traccar_root}

start_precmd=traccar_prestart
start_cmd=traccar_start

traccar_prestart()
{
    touch $pidfile
}

traccar_start()
{
    check_startmsgs && echo "Starting ${name}."
    su -l ${traccar_user} -c "exec ${command} ${command_args} ${rc_arg}"
}

run_rc_command "$1"

Which appears to start the deamon, but the logs state:

Code:
Exception in thread "main" java.io.FileNotFoundException: ./conf/default.xml (No such file or directory)

Which is the same error as the orginal script, so it seems the 'traccar_chdir' is not being executed (when using this script). Any ideas?
 
Maybe related, maybe not, but load_rc_config "${name}" is done twice in your script.
 
Maybe related, maybe not, but load_rc_config "${name}" is done twice in your script.

Thanks, the problem is that the chdir is not executed, the program starts, but does not find folders relative to the chdir location (which is the same error the original script had).
 
Yes, but it's odd it's using a relative directory when your script feeds it a fully qualified path (traccar_args), unless you're overriding traccar_root with '.'.
 
Yes, but it's odd it's using a relative directory when your script feeds it a fully qualified path (traccar_args), unless you're overriding traccar_root with '.'.

Yes it is strange, this program is a java (obviously) build. And the configuration files, reference other configuration files with a local path, so all though I pass

Code:
/usr/local/traccar/conf/traccar.xml

This file (and many others) contain references like:

Code:
<entry key='config.default'>.conf/default.xml</entry>

So unless this script is run inside /usr/local/traccar, it will run into problems.

EDIT, but my first attempt in the OP to write the script executes and launches it correctly. Just doesn't allow me to restart or get its status.
 
Hi,

I realize this thread is old, but since I've got the exact same problem I thought it might be necessary to revive this thread. I'm pretty new to this and am trying to run a traccar server in a truenas jail (12.2). I've followed the description on traccar's site for FreeBSD, realizing they are outdated, but stumpled on this thread here that gave me hope to make it happen, still.

So the installation itself went fine, installed openjdk11-jre (tried 8 as well, similar outcome, changed the path in the script accordingly, tho) but when I try to start the service it crashes right away, unfortunately, throwing this in the log file:

Code:
2021-02-01 21:57:01 ERROR: Main method error -  - SAXParseException (... < Config:37 < Context:276 < Main:137 < ...)
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: Configuration file is not a valid XML document
    at org.traccar.Main.run(Main.java:165)
    at org.traccar.Main.main(Main.java:110)
Caused by: java.lang.RuntimeException: Configuration file is not a valid XML document
    at org.traccar.config.Config.<init>(Config.java:52)
    at org.traccar.Context.init(Context.java:276)
    at org.traccar.Main.run(Main.java:137)
    ... 1 more
Caused by: java.util.InvalidPropertiesFormatException: jdk.internal.org.xml.sax.SAXParseException;
    at java.base/jdk.internal.util.xml.PropertiesDefaultHandler.load(Unknown Source)
    at java.base/java.util.Properties.loadFromXML(Unknown Source)
    at org.traccar.config.Config.<init>(Config.java:37)
    ... 3 more
Caused by: jdk.internal.org.xml.sax.SAXParseException;
    at java.base/jdk.internal.util.xml.impl.ParserSAX.panic(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.Parser.bname(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.Parser.name(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.Parser.dtd(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.Parser.step(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.ParserSAX.parse(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.ParserSAX.parse(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.ParserSAX.parse(Unknown Source)
    at java.base/jdk.internal.util.xml.impl.SAXPars

I see these pids:
Code:
root  54206  0.5  0.0   10976  1944  -  SsJ  21:53   0:00.01 daemon: /usr/local/openjdk11-jre/bin/java[54337] (daemon)
...
root  54337  0.0  0.2 5765644 34680  -  SJ   21:53   0:00.11 /usr/local/openjdk11-jre/bin/java -jar /usr/local/traccar/tracker-server.jar /usr/local/traccar/conf/traccar.xm

I wouldn't mind having to manually restart if that's the issue, but right now I'm not even getting it started at all... any help? Thanks!
 
Just by cooincidence I'm struggling with the same issue..

When debugging, I noted that "start" was being added to all my java arguements in the traccar_start() routine.. I futzed and fooled and just COULD NOT get variable substitution to play by the rules - same thing you are all encountering, I can run it fine manually, but try to leverage this RC script? Not so much..

What I finally did that IS working, start, status and stop all seem to do what I want... My fix was to abandon variable substitution in traccar_start().

Of course static paths make upgrades a bitch, but for NOW, I've got a thing running on FreeBSD without much official support, so I feel good!!

Good luck out there!!

-ET-

Code:
#!/bin/sh

## Service for traccar.

# PROVIDE: traccar
# REQUIRE: DAEMON mysql
# BEFORE:
# KEYWORD: shutdown

# Add the following lines to /etc/rc.conf to enable `traccar':
#
# traccar_enable="YES"
#

. /etc/rc.subr

name=traccar
desc="Traccar GPS tracking server"
rcvar=traccar_enable

load_rc_config "${name}"
: ${traccar_enable="YES"}
: ${traccar_root="/usr/local/traccar_4.12"}               # standard root
: ${traccar_args="-jar ${traccar_root}/tracker-server.jar ${traccar_root}/conf/traccar.xml"}
: ${traccar_java="/usr/local/openjdk8/jre/bin/java"}      # path to your JRE
: ${traccar_user="gts"}                                   # user to run as
: ${traccar_stdout="/var/log/traccar/traccar_running.log"}
: ${traccar_stderr="/var/log/traccar/traccar_error.log"}

pidfile=/var/run/traccar.pid
command=/usr/sbin/daemon
java_cmd="${traccar_java}"
procname="${java_cmd}"
command_args="-p ${pidfile} ${java_cmd} ${traccar_args}"
required_files="${java_cmd}"
traccar_chdir=${traccar_root}

start_precmd=traccar_prestart
start_cmd=traccar_start

traccar_prestart()
{
    touch $pidfile
}

traccar_start()
{
    check_startmsgs && echo "Starting ${name}."
    ## somehow, using variables just doesn't work here..  Bail.
    ##su -l ${traccar_user} -c "exec ${command} ${command_args} ${rc_arg}"
    /usr/bin/su -l gts -c "cd /usr/local/traccar_4.12; exec /usr/sbin/daemon \
    -p /var/run/traccar.pid /usr/local/openjdk8/jre/bin/java -jar \
    /usr/local/traccar_4.12/tracker-server.jar /usr/local/traccar_4.12/conf/traccar.xml"
}

run_rc_command "$1"
 
Sorry I didn't invest the time to thoroughly read your rc.d(8) script. A key point might be to start the service with the daemon(8) utilty: daemon -p <child_pidfile> .... In general this is necessary for any two-level service, i.e. scripted or run by in interpreter or bytecode-VM like Java or Python and the like. Eventually it's just
Bash:
...
traccar_start_cmd="daemon -p $pidfile_child -P $pidfile ..."
Please RTFM rc.subr(8) (search for run_rc_command) & if in doubt RTSL vi -R +/run_rc_command /etc/rc.subr
 
Back
Top