How to convert sysvinit script to systemd on Manjaro - linux

First, please don't consider this post as a systemd review or critic, but only and simply as a request for help.
Since I've not been able to find a solution to this problem with the systemd documentation, I've this question not solved for almost a year and a half that never ever received any answer.
So, here is the context:
I've a program (/opt/myprog) that can be sarted as a deamon service at boot time.
When using previous Debian, LMDE, Mint or Ubuntu OSes, I used SysVinit with the following script (myprog.sh within the /etc/init.d folder):
MYPROG_PATH=/opt/myprog_64
NAME="myprog"
START="-d"
STOP="-k"
TEST=""
VERSION="-v"
SCRIPTNAME=/etc/init.d/$NAME
STARTMESG="\nStarting $NAME in deamon mode.\n"
UPMESG="\$NAME is running.\n"
DOWNMESG="\$NAME is not running!\n"
TESTMESG="\nStarting NAME in client mode.\nHit Ctrl+C (or close the terminal) to stop mprog.\n"
STATUS=`pidof $NAME`
# Exit if myprog is not installed
[ -x "$MYPROG_PATH/$NAME" ] || exit 0
case "$1" in
start)
sleep 3
echo $STARTMESG
cd $MYPROG_PATH
./$NAME $START
;;
stop)
cd $MYPROG_PATH
./$NAME $STOP
;;
status)
if [ "$STATUS" > 0 ] ; then
echo $UPMESG
else
echo $DOWNMESG
fi
;;
restart)
cd $MYPROG_PATH
./$NAME $STOP
echo $STARTMESG
./$NAME $START
;;
version)
cd $MYPROG_PATH
./$NAME $VERSION
;;
test)
cd $MYPROG_PATH
echo $TESTMESG
./$NAME
;;
*)
echo "Usage: $SCRIPTNAME {start|status|restart|stop|version|test}" >&2
exit 3
;;
esac
:
Now, since it's obvious that systemd will be widely adopted to replace SysVinit including with future Debian, Mint and Ubuntu distros as it's with CentOS, Fedroa or Ach and Manjaro, I've tried to adapt my sysVinit script to systemd with the following script that works but is too limited (myprog.service):
Description=myprog
ConditionFileExecutable=/opt/myprog_64
After=NetworkManager.service
[Service]
Type=oneshot
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=/opt/myprog -d
ExecStop=/opt/myprog -k
ExecRestart=/opt/myprog-k : /opt/myprog -d
TimeoutSec=0
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
However, as systemd is advertised as compatible and more flexible than SysVinit, could anyone show me how to add the three following equivalent switches (status, test and version) that I have defined in the myprog.sh sysVinit script without responding with the classic and inelegant answer: "man is your friend" ?
/opt/myprog status to display the myprog status (i.e. running or not)
/opt/myprog test to start myprog not as a deamon
/opt/myprog version to display the release of myprog
Thank you in advance fo your time and help.

systemd does not support custom implementation of arguments to systemctl.
So systemctl status myprog will show the results based the execution of Exec* settings.
systemctl show myprog uses the Description so you can use a version in your description if desired.
If you wan't to run your program not as a daemon, then you can start it outside of systemd.

Related

debian init.d script not running after reboot

I need to start my Wildfly AS through .sh script after system boot (Linux-Debian). So I created my own script which should do it in init.d:
#! /bin/sh
# /etc/init.d/starter
case "$1" in
start)
echo "Starting"
nohup /home/xxx/wildfly-9.0.1.Final/bin/standalone.sh &
;;
stop)
echo "Stopping"
/home/xxx/wildfly-9.0.1.Final/bin/jboss-cli.sh --connect command=:shutdown
;;
*)
echo "Usage: /etc/init.d/starter {start|stop}"
exit 1
;;
esac
exit 0
This works if i use it on my own: /etc/init.d/starter start.
Then I used command to create symlinks: update-rc.d starter defaults. Symlinks are created just as expected, however after reboot command the script is not executed.
Does someone knows what prevents my script from being executed after boot? Thank you for all your advices.
Problem was that i did not know that initial script must set its own $PATH and other variables. I found it out when I saw java:not found in /var/log/daemon. At the end I found that wildfly has its own scirpt init-debian.sh. I used it and it works.

"can't cd" within init.d when started as service

I have a very simple script running in init.d to start a node server using forever. It has been working perfectly until recently and i cannot find what can have changed. I am on Debian 7, have not done any update recently.
This is my script (copied from somewhere, and kept simple simple, it is for tests )
#!/bin/sh
#/etc/init.d/nodeup
. /lib/lsb/init-functions
export PATH=$PATH:/usr/local/bin
export NODE_PATH=$NODE_PATH:/usr/local/lib/node_modules
. /home/pat/env
cd /var/www/mydir
FOREVER_ROOT=/var/log/forever/mydir
export FOREVER_ROOT
case "$1" in
start)
exec forever start -m 10 -o $FOREVER_ROOT/output.log -e $FOREVER_ROOT/error.log ./bin/www ./
;;
stop)
exec forever stop ./bin/www
;;
*)
echo "Usage: service nodeup {start|stop}"
exit 1
;;
esac
exit 0
The problem is that when I run (with start or stop, same effect)
sudo service nodeup start
I get
/etc/init.d/nodeup: 12: cd: can't cd to /var/www/mydir
if I run the script with sudo /etc/init.d/nodeup start
it runs perfectly, no problem.
I cannot understand what is going on, or what could have changed on my machine.
Any idea of what I should check that might give now this behaviour ? or what to change in my script so it works again ?
Thanks for any help
I changed the shell of the script from sh to bash
It seems to have rendered the script more stable

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),

Carbon 4.0.1 (BAM 2.0) as a Linux daemon

I am currently evaluating some of the WSO2 servers, one of them is the BAM 2.0 (on the carbon 4.0.1).
So far, in the packages was always a daemon.sh file included, which could be installed with chkconfig as a Linux daemon.
Sadly in the latest version of carbon, the daemon.sh is missing.
The startup script wso2server.sh can be used for starting the service, but it can not be installed as a linux daemon.
chkconfig returns:
[xxx#Server ~]$ sudo chkconfig --add wso2
service wso2 does not support chkconfig
I am trying this on a CentOS release 6.2 - 64 Bit.
Tried to find a description of how to install carbon as a linux daemon in the docs and in the forums - without success.
Thanks.
I rolled my own basic init script for BAM 2.0.0. (The following are parts from a file named 'bam'.)
#!/bin/sh
#
# chkconfig: 2345 80 80
#
BAM_HOME=/home/bam/current_bam
BAM_DAEMON=bin/wso2server.sh
START_OPTIONS=start
STOP_OPTIONS=stop
start() {
echo "Starting BAM... (it will take approx 2 mins.)"
su bam -c "cd $BAM_HOME && $BAM_DAEMON $START_OPTIONS > /dev/null 2>&1"
return 0
}
stop() {
echo "Stopping BAM... (it will take approx 10 secs.)"
su bam -c "cd $BAM_HOME && $BAM_DAEMON $STOP_OPTIONS > /dev/null 2>&1"
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
Then I copied it to /etc/init.d/ and made it executable. Lastly, I chkconfig'd it.
Now I can start the service with:
sudo service bam start

Adding a service startup script for Amazon linux AMI

I am using an Amazon Linux AMI and doing some custom modifications(added an axis2server, etc) on it and saving it as a new AMI. Now what I want to do is when the AMI boots up, start up axis2server(ie.axis2server should automatically start when the instance boots up). For that I used a init script like below and ran the following command:
chkconfig --add axisservice
But when I launch a new instance from my image, the axis2server is not getting started.
I just only need to execute the script /home/ec2-user/axis2-1.6.1/bin/axis2server.sh at startup. Am I missing anything here?
#! /bin/sh
# Basic support for IRIX style chkconfig
###
# chkconfig: 235 98 55
# description: Manages the services you are controlling with the chkconfig command
###
case "$1" in
start)
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh &
echo "."
;;
stop)
echo -n "Stopping axisservice"
echo "."
;;
*)
echo "Usage: /sbin/service axisservice {start|stop}"
exit 1
esac
exit 0
I went through https://help.ubuntu.com/community/CloudInit as well and it provides a mechanism called User-Data Scripts, where a user can execute a script when launching the script.
$ euca-run-instances --key mykey --user-data-file myscript.sh ami-axxxx
This is a command line option and what I want is something like when I launch the instance through the UI, the script should be started.Therefore, I think the above option can not be used in my case. Please correct me if I am wrong.
Thanks,
H.
I bet the environment is not set(up correctly). This means that I am guessing that your shell script tries to start another program and it's not to be found.
So at first, I'd adjust the start part of your script (current):
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh &
echo "."
Edited:
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh
RETVAL=$?
[ $RETVAL -eq 0 ] && echo Success
[ $RETVAL -ne 0 ] && echo Failure
echo "."
So what did I do?
removed & so script waits for your shell script (axis2server.sh) to complete
checked the return status ($?) of your shell script
Further debugging:
Add set -x to your scripts to enable tracing and log both stderr and stdout.
Questions:
Are you are aware that stop (in your service script) doesn't do anything?
touch ~/temp.txt is that supposed to create /root/temp.txt? (I'm guessing root runs this script.)
If none of my suggestions work, can you share axis2server.sh and paste stderr and stdout?

Resources