Service that uses libcurl not auto-starting on Debian? - linux

I've written and compiled a daemon program in C which is meant to run in the background with root access. My program uses libcurl to make some occasional network calls. I've also written a simple init.d script to govern its startup and shutdown procedures. I would like this service to automatically start on boot, and based on what I've done I would expect it to already be doing this. However, I'm noticing an error in the logs relating to libcurl, and as a result the service is not being started automatically.
My program is located in /usr/bin/myprog and I have the following bash script located in /etc/init.d/myprog:
#!/bin/bash
### BEGIN INIT INFO
# Provides: myprog
# Required-Start: $remote_fs $network $syslog
# Required-Stop: $remote_fs $network $syslog
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: myprog
# Description: My Daemon Program
### END INIT INFO
. /lib/lsb/init-functions
SCRIPT=/usr/bin/myprog
PIDFILE=/var/run/myprog.pid
start() {
if [ -f $PIDFILE ]; then
echo "Service is already started"
return 2
else
$SCRIPT
$RETVAL="$?"
return "${RETVAL}"
fi
}
stop() {
if [ -f $PIDFILE ]; then
kill $(cat $PIDFILE)
rm -f $PIDFILE
return 0
else
echo "Service is not running"
return 2
fi
}
case "$1" in
start)
log_daemon_msg "Starting myprog" "myprog"
start
;;
stop)
log_daemon_msg "Stopping myprog" "myprog"
stop
;;
status)
status_of_proce "$SCRIPT" "myprog" && exit 0 || exit $?
;;
restart)
log_daemon_msg "Restarting myprog" "myprog"
stop
start
;;
*)
echo $"Usage: $0 {start|stop|status|restart}" >&2
exit 3
;;
esac
I then ran sudo update-rc.d myprog defaults and this created the following files:
/etc/rc0.d/K01myprog
/etc/rc1.d/K01myprog
/etc/rc2.d/K01myprog
/etc/rc3.d/S02myprog
/etc/rc4.d/S02myprog
/etc/rc5.d/S02myprog
/etc/rc6.d/K01myprog
And as far as I can tell, each of those 7 files are identical copies of the one I posted above. Based on the various tutorials and forums I've been reading, I would think this would be sufficient. However, my service does not appear to be auto-starting on boot. If I call sudo /etc/init.d/myprog start directly, then it starts up fine. But otherwise it does not appear to be launched.
I then noticed an error message in the logs which said "curl error: could not resolve host," even though the particular host it was referencing was definitely valid. So I think perhaps it's trying to launch my application before something that libcurl needs is ready, and is therefore failing to launch. Again, if I launch it manually it works fine. How can I fix this?

If DNS resolution is the point of failure then use the IP address instead. If you are unwilling to use the IP address, add the hostname and IP address to /etc/hosts.

Related

My application speed is low when run at linux startup

I have an embedded console application created with Qt,C++. I use nanopi fire (FriendlyARM) for my device with Linux arch. I connect it's gpio as relay for turning on and off the lamps of my room. Also I wrote mobile app to connect the device with socket. When I run my program from putty ./SmartKeyC it runs and I can switch the lamps with my mobile app buttons and all of them are ok.
But when I put my program on start up for auto run, all of functions do their tasks with 2-3 seconds delay.
I used this link to create auto run app. this is my script:
#! /bin/sh
### BEGIN INIT INFO
# Provides: <your script name>
# Required-Start: $all
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Manage my cool stuff
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/root
. /lib/init/vars.sh
. /lib/lsb/init-functions
. /root/
# If you need to source some other scripts, do it here
case "$1" in
start)
log_begin_msg "Starting my super cool service"
# do something
/root/SmartKeyC
log_end_msg $?
exit 0
;;
stop)
log_begin_msg "Stopping the coolest service ever unfortunately"
# do something to kill the service or cleanup or nothing
log_end_msg $?
exit 0
;;
*)
echo "Usage: /etc/init.d/<your script> {start|stop}"
exit 1
;;
esac
and after update rc I have:
root#NanoPi2-Fire:/etc# find -iname "*SmartKeyScript"
./init.d/SmartKeyScript
./rc0.d/K01SmartKeyScript
./rc1.d/K01SmartKeyScript
./rc2.d/S03SmartKeyScript
./rc3.d/S03SmartKeyScript
./rc4.d/S03SmartKeyScript
./rc5.d/S03SmartKeyScript
./rc6.d/K01SmartKeyScript
Where is the problem?
Why when I run my app in putty , everything works good , but when my app starts from auto run it has delay for each function calling?
I remove my script from rcX and put file in my rc.local like below:
Vi /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/usr/local/bin/gen-friendlyelec-release
. /etc/friendlyelec-release
if [ ! -f /etc/firstuse ]; then
/bin/echo ${BOARD} > /etc/hostname
/bin/sed -i "s/\(127.0.1.1\s*\).*/\1${BOARD}/g" /etc/hosts
/bin/hostname ${BOARD}
/bin/echo "0" > /etc/firstuse
fi
. /usr/bin/setqt5env
/usr/bin/lcd2usb_print "CPU: {{CPU}}" "Mem: {{MEM}}" "IP: {{IP}}" "LoadAvg: {{LOADAVG}}" 2>&1 > /dev/null&
#/opt/QtE-Demo/run.sh&
/root/SmartKeyC & > /dev/tty0
exit 0

Script run at shutdown debian

So I am trying to write a basic script that runs a shutdown and copies some logs. To start with I made it simple so that it just prints some text into a file as it runs to help me understand a bit further. The problem is that it appears that the script is never called. Calling it manually runs as expected, but it never runs at shutdown.
#! /bin/sh
### BEGIN INIT INFO
# Provides: cpylogs
# Required-Start:
# Required-Stop:
# Should-Stop:
# Default-Start: 0 6
# Default-Stop: 0 6
# Short-Description:
# Description:
#
#
### END INIT INFO
FILE=/shutdown.txt
echo "called" > $FILE
do_stop (){
echo "in stop function" >> $FILE
}
case "$1" in
start|status)
echo "start" >> $FILE
exit 1
;;
restart|reload|force-reload)
echo "restart etc" >> $FILE
exit 1
;;
stop|"")
do_stop
echo "stop" >> $FILE
exit 1
;;
*)
echo "default" >> $FILE
exit 1
;;
esac
This is saved in /etc/init.d/ as cpylogs. Then I placed the links in /etc/rc0.d/ and /etc/rc6.d by calling sudo update-rd.d cpylogs defaults, which places the appropriate K01cpylogs in each. I have also tried doing the links manually with no luck their either. I have also tried changing the priority to K99 which still doesn't work. Any suggestions?
Further info, Running Debian 8.4, on a beaglebone
Update: I have changed it slightly # Default-Start: 2 3 5 so it runs at startup. It runs perfectly fine at startup, but still doesn't run at shutdown.
Probably better posted on superuser.com
possible solution here : unix.stackexchange.com
and here : https://www.centos.org/forums/viewtopic.php?t=14582

How do I run a simple Go server as a daemon in Debian?

I recently wrote a simple server in Go:
package main
import (
"net/http"
"fmt"
"os/exec"
)
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":****", nil)
}
func handler(output http.ResponseWriter, input *http.Request) {
instruction := "Instructed to " + input.URL.Path[1:] + "."
fmt.Printf(instruction)
if input.URL.Path[1:] == "********" {
*************
*************
*************
if err != nil {
fmt.Println("There was a problem executing the script.")
}
} else {
fmt.Println(" I'm unfamiliar with this instruction.")
}
}
It works perfectly well if compiled and then executed by ./go_http_server &.
The problem is that it doesn't survive reboots. So after some reading, I attempted to daemonize it by placing a script in /etc/init.d:
#!/bin/sh
### BEGIN INIT INFO
# Provides: myservice
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Put a short description of the service here
# Description: Put a long description of the service here
### END INIT INFO
# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/****/****
DAEMON=$DIR/go_http_server
DAEMON_NAME=*********
# Add any command line options for your daemon here
DAEMON_OPTS=""
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=*****
# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
...then running update-rc.d go_http_server defaults, and poof! It runs on boot, as verified by ps -ef | grep go_http_server.
But it doesn't receive GET requests while running as a service. Thinking it might be running before the network interface was up, I tried service go_http_server stop, followed by service go_http_server start; still refused to receive GET requests. Stopping the service again and then executing ./go_http_server & makes the server function correctly once more.
I've been Googling this on and off for a couple days now. Either my search queries suck, or this isn't an obvious problem. How do I daemonize my Go server?
EDIT: The exact same thing happens with a server I wrote in Python: it works as it should when executed using ./python_server.py, but--if started as service--HTTP requests are ignored. Both files have been made executable, and it doesn't matter if the daemon user is root or any other user. Not sure if this helps, but I thought it might be relevant.
Supervisor is a good fit here, and can automatically capture and rotate logs written to stdout, restart on crash and manage ports/permissions.
Here's what an example configuration would look like for a Go web service:
# where 'mygoapp' is the name of your application
$ sudo vim /etc/supervisor/conf.d/mygoapp.conf
[program:yourapp]
command=/home/yourappuser/bin/yourapp # the location of your app
autostart=true
autorestart=true
startretries=10
user=yourappuser # the user your app should run as (i.e. *not* root!)
directory=/srv/www/yourapp.com/ # where your application runs from
environment=APP_SETTINGS="/srv/www/yourapp.com/prod.toml" # environmental variables
redirect_stderr=true
stdout_logfile=/var/log/supervisor/yourapp.log # the name of the log file.
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
I wrote an article[1] that takes you through the steps, but the Supervisor documentation is extremely comprehensive.
Similarly, Debian systems also use systemd[2], which can achieve this as well.

update-rc.d disable/remove will not remove etc/init.d/rc* references

I have created a daemon using the Debian init.d skeleton which successfully runs as a service. I've also used:
sudo update-rc.d /etc/init.d/pirservice.sh defaults
to get the daemon running at boot and closing nicely when issuing a shutdown command.
However, I have since tried to remove the start at boot service using the following:
sudo update-rc.d /etc/init.d/pirservice.sh remove
On checking for completion using:
ls -l /etc/rc?.d/*pirservice.sh
The scripts is still linked in all 6 rc?.d folders and sure enough still loads at boot
when I try to use the following:
sudo update-rc.d /etc/init.d/pirservice.sh disable
I get the following error:
update-rc.d: using dependency based boot sequencing
update-rc.d: error: cannot find a LSB script for /etc/init.d/pirservice.sh
My scripts is as follows:
#!/bin/sh
# /etc/init.d/pirservice.sh
### BEGIN INIT INFO
# Provides: myservice
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Put a short description of the service here
# Description: Put a long description of the service here
### END INIT INFO
# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/usr/local/bin/myservice
DAEMON=$DIR/pir.py
DAEMON_NAME=pir
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root
# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --startas $DAEMON
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;
*)
echo "Usage: /etc/init.d/$DEAMON_NAME {start|stop|restart|status}"
exit 1
;;
esac
exit 0
Can anyone offer any guidance?
OK. I couldn't see any obvious error with the init script. so I forced the removal as follows:
sudo update-rc.d -f /etc/init.d/pirservice.sh remove
If anyone can figure out why I have the LSB error I would be appreciative.
The man page says
update-rc.d [-n] [-f] name remove
update-rc.d updates the System V style init script links /etc/rcrunlevel.d/NN*name* whose target is the script /etc/init.d/name.
So you should use
update-rc.d pirservice.sh disable
instead.
For good style you should update information within the INIT INFO block.
Additionaly you could remove the .sh extension for a nicer name.

How to get this init.d script to start at server restart?

I'm following the directions on installing Redis on a production machine (CentOS using chkconfig).
The example script I was given requires the argument start to actually start it, which it seems init.d does not do (pass arguments).
The real command that must be run is /etc/init.d/redis_6379 start, but what its actually calling is /etc/inti.d/redis_6379, which simply says use start or stop as an argument
Therefor, when my server reboots it doesnt actually start redis. What should I do here?
Here is the initial config
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
#
# chkconfig: - 85 15
# description: Redis is a persistent key-value database
# processname: redis_6379
REDISPORT=6379
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli
PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
Make sure your script is added for service management by chkconfig. Use chkconfig --list to see the list and use chkconfig --add scriptname if it's not there. After that configure the runlevels you want it to be called into. I would guess it's 3, 4 and 5 so: chkconfig --level 345 scriptname on.
You should tell us how exactly you are running the script from init.d
But here is a dirty workaround:
Change the line
start)
to
start|'')
This will make it start if there are no parameters passed.
If you want to start a service through command line you can just add in /etc/rc.d/rc.local too for the same instead of creating a service file in init.d.
Centos redis has an init script with a chkconfig header line stating that it will start in all runlevels, which is very bad. chkconfig is used to manage the symlinks in /etc/rc.d
# chkconfig: - 85 15
I suggest that redis is a service to run in level 3 after critical services have launched (sshd for instance). In your test scenario's reboot your server before going to production. If redis cannot launch (just happened here) you cannot boot it in another runlevel to fix it.
If you implement the proper headers you can use init and also systemd (Fedora)
Your should add code below to the script /etc/inti.d/redis_6379. The status argument is used by command service --status-all.
# processname: redis_6379
# Source function library.
. /etc/init.d/functions
...
case "$1" in
status)
status -p $PIDFILE redis
script_result=$?
;;
Init.d's days are numbered, wtf are you still reading this for? There's no more sudo service, all the new kids are slapping down syscrtl
Nowadays like of course on my ubuntu 17.04 server at work, /etc/rc.local didn't even exist
Just write a new one!
rc.local is awesome, especially combined with the unix style daemonize program... those two alone, I can pretty much call it a day.
However, if you want to take rc.local to the next level, I'll cover basic ideas behind my own personal redis init.d script--same one we use on production servers across my company:
pre-empt redis complaint about system socket/file limits
slap in some linux perf and mess around with sysconf in persistent fashion
autopilot redis while i go take a nap
#!/bin/sh
### BEGIN INIT INFO
# Provides: redis
# Required-Start: $syslog
# Required-Stop: $syslog
# Should-Start: $all
# Should-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: start and stop redis
# Description: persistent key-value db
### END INIT INFO
NAME=redis
PATH=/opt/bin:/opt/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
EXEC=/opt/sbin/redis-server
CLIEXEC=/opt/sbin/redis-cli
CONF=/etc/$NAME/$NAME.conf
PIDFILE=/var/run/$NAME.pid
SOCKET=/var/run/$NAME.sock
PERF=/tmp/redis.sysctl
KERNELPG=/sys/kernel/mm/transparent_hugepage/enabled
[ -x /opt/sbin/redis-server ] || exit 0
set -e
# tune system for better redis performance
if [ ! -f $PERF ]; then
echo "tunning redis..." &>> $PERF
echo never > $KERNELPG && cat $KERNELPG &>> $PERF
sysctl -w net.core.somaxconn=65535 &>> $PERF
sysctl -w vm.overcommit_memory=1 &>> $PERF
echo "tuned." &>> $PERF && cat $PERF
fi
next, if we're doin' it right:
let's have nice idiomatic case $money numbers, focused on starting and stopping without sorting through excessive PID tracking shenanigans
take advantage of the start-stop-daemon (i.e. can't get cut short by parent process death if there is no parent process)
case $1 in
start)
if [ ! -f $PIDFILE ]; then
echo -n "Starting $NAME: "
start-stop-daemon --start --pidfile $PIDFILE --exec $EXEC -- $CONF
echo "waiting for redis db to start..."
while [ ! -f $PIDFILE ]; do
sleep 0.1;
done
fi
PID=$(cat $PIDFILE)
echo "running with pid: $PID"
;;
stop)
if [ ! -f $PIDFILE ]; then
echo "redis is already stopped"
else
PID=$(cat $PIDFILE)
echo -n "Stopping $NAME: "
$CLIEXEC -s $SOCKET shutdown
echo "waiting for shutdown..."
while [ -x /proc/${PID} ]; do
sleep 0.1
done
echo "db stopped."
fi
;;
status)
if [ -f $PIDFILE ]; then
PID=$(cat $PIDFILE)
echo "running with pid: $PID"
else
echo "stopped."
fi
;;
restart|force-reload)
$0 stop && $0 start
;;
*)
echo "Argument \"$1\" not implemented."
exit 2
;;
esac
exit 0
edit redis.conf to designate daemonize yes. Make redis the primary responsible party for administrative PID file state (in case you were wondering why we didn't have to do anything with it in the script, except read from it if it's around)
mkdir /etc/redis
echo 'daemonize yes' >> /etc/redis/redis.conf
echo 'pidfile /var/run/redis.pid' >> /etc/redis/redis.conf
update your rc entry by name after copying and setting execution bits:
mkdir /etc/redis
vim /etc/redis/redis # keep it traditional, no .sh extensions here
# saving buffers from root all damn day...
chmod a+x /etc/init.d/redis
update-rc.d redis defaults
Here's the full example link w/ service installer. Again, be sure to edit conf and install to suit you. Most people would probably want to remove the listening file path in favor of TCP stack w/ redis port number open for client(s),

Resources