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.
I am writing a shell script and here is the snippet ..
sudo service httpd restart --- ( 1)
if [ $? -eq 0 ]; then
# Now configure php.ini using sed command
sudo sed -i 's_;date.timezone =_date.timezone = "Asia/Kolkata"_' /etc/php.ini
# Now restart the httpd server again
sudo service httpd restart ---- This statement throws error
When I ran above script then I got error Address already in use: make_sock: could not bind to address at second sudo service httpd restart statement.
I doubt it is because when first time sudo service httpd restart runs , before it finishes completely second 'sudo service httpd restart' runs.
So how can I test surely If first sudo service httpd restart finishes then only rest of the code execute.
I hope I am understandable ..
Thanks
Forget the [ giving:
if sudo service http restart; then
# stuff
if sudo service http restart; then
echo ok
else
# error handling for second service failure
fi
else
# error handling for first failure
fi
Commands are true if their return status is zero, false otherwise. Shell commands also must terminate before the next line is called.
It is possible, in principle, that service does stuff in the background and exits before completion. In practice, it doesn't because that would really screw things up.
Not sure if the command backgrounds. If so, you could check if your command is still to be found in the process list:
// ... your code ...
c=1
while [[ c -gt 0 ]]
do
c=`ps l | grep -c "service httpd restart"`
done
service httpd restart
I'm running Arch-based Manjaro Linux and wrote myself a little update program, that starts every 7 hours and runs completely in the background. This update program is started by systemd.
What I wanna know is: How can I prevent any system shutdown/reboot during the time this program runs no matter if the user just wants to turn it off or any program wants to do so.
The best would be, if any shutdown/reboot action wouldn't be cancelled but delayed instead, so when the update program has finished its run, the shutdown/reboot continues.
My systemd parts are:
uupgrades.timer
[Unit]
Description=UU Upgrades Timer
[Timer]
OnBootSec=23min
OnUnitActiveSec=7h
Unit=uupgrades.target
[Install]
WantedBy=basic.target
uupgrades.target
[Unit]
Description=UU Upgrades Timer Target
StopWhenUnneeded=yes
and in the folder uupgrades.target.wants
uupgrades.service
[Unit]
Description=UU Update Program
[Service]
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
ExecStart=/usr/bin/uupgrades
How can I achieve this?
If a user with sufficient permissions to reboot the server or manipulate processes wants to stop or reboot the machine you cant stop them. That's just how linux works. You should set up permissions and accounts such that no other users have root permissions or permissions sufficient to manipulate the process or user that the process is running as.
When I want to block myself from rebooting or shutdown, I alias my usual shutdown and reboot aliases to beep;beep;beep;.
In multiuser environments you could move the reboot, shutdown etc. binaries and move them back, when shutdown should be allowed again.
You could also temporarily move an executable shell script outputting information about the postponed shutdown possibility in place of the corresponding binaries. This script could set a flag, if a shutdown was requested.
Q&D example script:
#!/usr/bin/env bash
echo "preventing reboot"
BACKUPBINARY_REBOOT=$(mktemp);
mv /bin/reboot $BACKUPBINARY_REBOOT;
FLAGFILE=$(mktemp);
echo '#!/usr/bin/env bash' > /bin/reboot;
echo '# original reboot binary was moved to'"$BACKUPBINARY_REBOOT" >> /bin/reboot;
echo 'echo request-reboot > '"$FLAGFILE" >> /bin/reboot;
echo 'echo reboot is prevented, your request will trigger later' >> /bin/reboot;
chmod 666 "$FLAGFILE";
chmod +x /bin/reboot;
echo "postponed reboot - press enter to allow it again and make up for requested reboot";
read;
mv "$BACKUPBINARY_REBOOT" /bin/reboot;
if grep -q request-reboot "$FLAGFILE"; then
rm $FLAGFILE;
/bin/reboot;
fi
You can add another systemd service at /usr/lib/systemd/system-shutdown/ which will be run at shutdown, and have it check if your update script is running, and if so, cancel or delay the shutdown.
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
I'm trying to ensure a script remains running on a development server. It collates stats and provides a web service so it's supposed to persist, yet a few times a day, it dies off for unknown reasons. When we notice we just launch it again, but it's a pain in the rear and some users don't have permission (or the knowhow) to launch it up.
The programmer in me wants to spend a few hours getting to the bottom of the problem but the busy person in me thinks there must be an easy way to detect if an app is not running, and launch it again.
I know I could cron-script ps through grep:
ps -A | grep appname
But again, that's another hour of my life wasted on doing something that must already exist... Is there not a pre-made app that I can pass an executable (optionally with arguments) and that will keep a process running indefinitely?
In case it makes any difference, it's Ubuntu.
I have used a simple script with cron to make sure that the program is running. If it is not, then it will start it up. This may not be the perfect solution you are looking for, but it is simple and works rather well.
#!/bin/bash
#make-run.sh
#make sure a process is always running.
export DISPLAY=:0 #needed if you are running a simple gui app.
process=YourProcessName
makerun="/usr/bin/program"
if ps ax | grep -v grep | grep $process > /dev/null
then
exit
else
$makerun &
fi
exit
Then add a cron job every minute, or every 5 minutes.
Monit is perfect for this :)
You can write simple config files which tell monit to watch e.g. a TCP port, a PID file etc
monit will run a command you specify when the process it is monitoring is unavailable/using too much memory/is pegging the CPU for too long/etc. It will also pop out an email alert telling you what happened and whether it could do anything about it.
We use it to keep a load of our websites running while giving us early warning when something's going wrong.
-- Your faithful employee, Monit
Notice: Upstart is in maintenance mode and was abandoned by Ubuntu which uses systemd. One should check the systemd' manual for details how to write service definition.
Since you're using Ubuntu, you may be interested in Upstart, which has replaced the traditional sysV init. One key feature is that it can restart a service if it dies unexpectedly. Fedora has moved to upstart, and Debian is in experimental, so it may be worth looking into.
This may be overkill for this situation though, as a cron script will take 2 minutes to implement.
#!/bin/bash
if [[ ! `pidof -s yourapp` ]]; then
invoke-rc.d yourapp start
fi
If you are using a systemd-based distro such as Fedora and recent Ubuntu releases, you can use systemd's "Restart" capability for services. It can be setup as a system service or as a user service if it needs to be managed by, and run as, a particular user, which is more likely the case in OP's particular situation.
The Restart option takes one of no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, or always.
To run it as a user, simply place a file like the following into ~/.config/systemd/user/something.service:
[Unit]
Description=Something
[Service]
ExecStart=/path/to/something
Restart=on-failure
[Install]
WantedBy=graphical.target
then:
systemctl --user daemon-reload
systemctl --user [status|start|stop|restart] something
No root privilege / modification of system files needed, no cron jobs needed, nothing to install, flexible as hell (see all the related service options in the documentation).
See also https://wiki.archlinux.org/index.php/Systemd/User for more information about using the per-user systemd instance.
I have used from cron "killall -0 programname || /etc/init.d/programname start". kill will error if the process doesn't exist. If it does exist, it'll deliver a null signal to the process (which the kernel will ignore and not bother passing on.)
This idiom is simple to remember (IMHO). Generally I use this while I'm still trying to discover why the service itself is failing. IMHO a program shouldn't just disappear unexpectedly :)
Put your run in a loop- so when it exits, it runs again... while(true){ run my app.. }
I couldn't get Chris Wendt solution to work for some reason, and it was hard to debug. This one is pretty much the same but easier to debug, excludes bash from the pattern matching. To debug just run: bash ./root/makerun-mysql.sh. In the following example with mysql-server just replace the value of the variables for process and makerun for your process.
Create a BASH-script like this (nano /root/makerun-mysql.sh):
#!/bin/bash
process="mysql"
makerun="/etc/init.d/mysql restart"
if ps ax | grep -v grep | grep -v bash | grep --quiet $process
then
printf "Process '%s' is running.\n" "$process"
exit
else
printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun"
$makerun
fi
exit
Make sure it's executable by adding proper file permissions (i.e. chmod 700 /root/makerun-mysql.sh)
Then add this to your crontab (crontab -e):
# Keep processes running every 5 minutes
*/5 * * * * bash /root/makerun-mysql.sh
The supervise tool from daemontools would be my preference - but then everything Dan J Bernstein writes is my preference :)
http://cr.yp.to/daemontools/supervise.html
You have to create a particular directory structure for your application startup script, but it's very simple to use.
first of all, how do you start this app? Does it fork itself to the background? Is it started with nohup .. & etc? If it's the latter, check why it died in nohup.out, if it's the first, build logging.
As for your main question: you could cron it, or run another process on the background (not the best choice) and use pidof in a bashscript, easy enough:
if [ `pidof -s app` -eq 0 ]; then
nohup app &
fi
You could make it a service launched from inittab (although some Linuxes have moved on to something newer in /etc/event.d). These built in systems make sure your service keeps running without writing your own scripts or installing something new.
It's a job for a DMD (daemon monitoring daemon). there are a few around; but I usually just write a script that checks if the daemon is running, and run if not, and put it in cron to run every minute.
Check out 'nanny' referenced in Chapter 9 (p197 or thereabouts) of "Unix Hater's Handbook" (one of several sources for the book in PDF).
A nice, simple way to do this is as follows:
Write your server to die if it can't listen on the port it expects
Set a cronjob to try to launch your server every minute
If it isn't running it'll start, and if it is running it won't. In any case, your server will always be up.
I think a better solution is if you test the function, too. For example, if you had to test an apache, it is not enough only to test, if "apache" processes on the systems exist.
If you want to test if apache OK is, then try to download a simple web page, and test if your unique code is in the output.
If not, kill the apache with -9 and then do a restart. And send a mail to the root (which is a forwarded mail address to the roots of the company/server/project).
It's even simplier:
#!/bin/bash
export DISPLAY=:0
process=processname
makerun="/usr/bin/processname"
if ! pgrep $process > /dev/null
then
$makerun &
fi
You have to remember though to make sure processname is unique.
One can install minutely monitoring cronjob like this:
crontab -l > crontab;echo -e '* * * * * export DISPLAY=":0.0" && for
app in "eiskaltdcpp-qt" "transmission-gtk" "nicotine";do ps aux|grep
-v grep|grep "$app";done||"$app" &' >> crontab;crontab crontab
disadvantage is that the app names you enter have to be found in ps aux|grep "appname" output and at same time being able to be launched using that name: "appname" &
also you can use the pm2 library.
sudo apt-get pm2
And if its a node app can install.
Sudo npm install pm2 -g
them can run the service.
linux service:
sudo pm2 start [service_name]
npm service app:
pm2 start index.js