Is there a way to pipe a value into a daemon so that when the daemon starts it populates the service options required to start successfully. I'm running Debian 9 and here is a snippet of code:
start-stop-daemon --start --chuid $USER \
$START_STOP_OPTIONS --exec $DAEMON -- \
--username $VPN_USER --password $VPN_PASSWORD --domain $VPN_DOMAIN \
$OPTIONS $VPN_SERVER:$VPN_SERVER_PORT&
Ideally I need to parse Y into the daemon otherwise the service being executed by the daemon cannot start correctly. I've tried a mixture of stdin from echo >>> <<< inside and outside of --exec but no luck...
TLDR;
How do I get this to work?
echo "Y" | start-stop-daemon ...
The proper way to do this is to have a -y switch(for example) in the program arguments that will start the daemon without prompts. In general it's a very bad practice to not have this option.
Otherwise I just tested with a simple python script that prompts for "Y" and it works.
Script:
#!/usr/bin/python3
from time import sleep
k = input("prompt:")
if k == "Y":
print("exit!")
exit(1)
while True:
sleep(100)
I run it like echo "Y" | start-stop-daemon --start --exec /home/user/tests/startd.py and it prints exit! and exits.
If it is the case that it requires multiple "Y"s you can try the yes program like
yes "Y" | start-stop-daemon --start --exec yourdaemon.
Related
on my raspberry pi (raspbian running) I would like to have the current desktop switched to desktop n#0 after 5 minutes of idle system (no mouse or keyboard action), through wmctrl -s 0 and xprintidle for idle time checking.
Please keep in mind I'm no expert...
I tried 2 different ways, none of them working and I was wondering which one of them is the best way to do have the job done:
bash script and crontab
I wrote a simple script which checks if xprintidle is greater than a previously set $IDLE_TIME, than it switches desktops (saved in /usr/local/bin/switchDesktop0OnIdle):
#!/bin/bash
# 5 minutes in ms
IDLE_TIME=$((5*60*1000))
# Sequence to execute when timeout triggers.
trigger_cmd() {
wmctrl -s 0
}
sleep_time=$IDLE_TIME
triggered=false
while sleep $(((sleep_time+999)/1000)); do
idle=$(xprintidle)
if [ $idle -ge $IDLE_TIME ]; then
if ! $triggered; then
trigger_cmd
triggered=true
sleep_time=$IDLE_TIME
fi
else
triggered=false
# Give 100 ms buffer to avoid frantic loops shortly before triggers.
sleep_time=$((IDLE_TIME-idle+100))
fi
done
script itself works.
Then I added it to crontab (crontab -e) for have it run every 6 minutes
*/6 * * * * * sudo /usr/local/bin/switchDesktop0OnIdle
not sure sudo is necessary or not.
Anyway It doesn't work: googling around I understood that crontab runs in its own environment with its own variables. Even though I don't remember how to access this environment (oops) I do remember that I get these 2 errors running the script in it (which correctly works in "normal" shell)
could not open display (is it important ?)
bla bla -ge error, unary operator expected or similar: basically xprintidle doesn't work in this environment a gives back an empty value
What am I missing ?
infinite-while bash script running as daemon
second method I tried to set up a script with an internal infinite-while checking if xprintidle is greater then 5 minutes. In this case desktop is switched (less elegant?). Saved also in /usr/local/bin/switchDesktop0OnIdle
#!/bin/bash
triggered=false
while :
do
if [ `xprintidle` -ge 300000 ]; then
if [ triggered == false ]
wmctrl -s 0
triggered = true
fi
else
triggered = false
fi
fi
done
again the script itself works.
I tried to create a daemon in /etc/init.d/switchDesktop0OnIdle (really not an expert here, modified an existing one)
#! /bin/sh
# /etc/init.d/switchDesktop0OnIdle
### BEGIN INIT INFO
# Provides: switchDesktop0OnIdle
# Required-Start: $all
# Required-Stop: $all
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description:
# Description:
### END INIT INFO
DAEMON=/usr/local/bin/switchDesktop0OnIdle
NAME=switchDesktop0OnIdle
test -x $DAEMON || exit 0
case "$1" in
start)
echo -n "Starting daemon: "
start-stop-daemon --start --exec $DAEMON
echo "switchDesktop0OnIdle."
;;
stop)
echo -n "Shutting down daemon:"
start-stop-daemon --stop --oknodo --retry 30 --exec $DAEMON
echo "switchDesktop0OnIdle."
;;
restart)
echo -n "Restarting daemon: "
start-stop-daemon --stop --oknodo --retry 30 --exec $DAEMON
start-stop-daemon --start --exec $DAEMON
echo "switchDesktop0OnIdle."
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
I set it up
sudo update-rc.d switchDesktop0OnIdle defaults
and
sudo service switchDesktop0OnIdle start
(necessary?)
...and nothing happens...
also I don't find the process with ps -ef | grep switchDesktop0OnIdle but it seems running with sudo service switchDesktop0OnIdle status
can anyone please help?
thank you
Giuseppe
As you suspected, the issue is that when you run your scripts from init or from cron, they are not running within the GUI environment you want them to control. In principle, a Linux system can have multiple X environments running. When you are using one, there are environment variables that direct the executables you are using to the environment you are in.
There are two parts to the solution: your scripts have to know which environment they are acting on, and they have to have authorization to interact with that environment.
You almost certainly are using a DISPLAY value of ":0", so export DISPLAY=:0 at the beginning of your script will handle the first part of the problem. (It might be ":0.0", which is effectively equivalent).
Authorization is a bit more complex. X can be set up to do authorization in different ways, but the most common is to have a file .Xauthority in your home directory which contains a token that is checked by the X server. If you install a script in your own crontab, it will run under your own user id (you probabl shouldn't use sudo), so it will read the right .Xauthority file. If you run from the root crontab, or from an init script, it will run as the root user, so it will have access to everything but will still need to know where to take the token from. I think that adding export XAUTHORITY=/home/joe/.Xauthority to the script will work. (Assuming your user id is joe.)
I found a init.d script template -- filled in the blanks and tried to invoke GAE using something like:
start-stop-daemon -S --background python
/opt/google_appengine/dev_appserver.py --host=0.0.0.0
--admin_host=0.0.0.0 --php_executable_path=/usr/bin/php-cgi /var/www
This doesn't work...but if I run from the command line works fine but hangs the input...
How do I invoke this command at startup using init.d and change to the user "gae" -- similar to Apache runs as www-data
I also (briefly) tried to use start-stop-daemon to control Google App Engine (without any luck), so I ended up using /etc/rc.local to launch the daemon.
Add the following to /etc/rc.local (before any exit command):
sudo -i -u gae python /opt/google_appengine/dev_appserver.py --host=0.0.0.0 \
--storage_path /var/cache/appengine/gae \
--admin_host=0.0.0.0 --php_executable_path=/usr/bin/php-cgi /var/www > /dev/null 2> /dev/null &
Note, I included a storage_path in the launch options. Make sure you do the following:
sudo mkdir -p /var/cache/appengine/gae
sudo chown gae: /var/cache/appengine/gae
To restart the process (after an update), I just kill python and manually execute rc.local:
sudo killall -9 python
sudo /etc/rc.local
I have finally figured out how and why the start-stop-daemon was not working...it all boiled down to some simple syntactical errors and a (still?) misunderstanding on my behalf:
https://unix.stackexchange.com/questions/154692/start-stop-daemon-wont-start-my-python-script-as-service
In brief, when I use this init.d script and register it accordingly, GAE starts and stops accordingly:
#!/bin/sh
### BEGIN INIT INFO
# Provides: Google App Engine daemon management
# Required-Start:
# Required-Stop:
# Default-Start:
# Default-Stop:
# Short-Description: Google App Engine initscript
# Description: Start/stop appengine web server
### END INIT INFO
# Author: Alex Barylski <alex.barylski#gmail.com>
. /lib/lsb/init-functions
#
# Initialize variables
#
name=appengine
desc="Google App Engine"
bind=0.0.0.0
docroot=/var/www
phpexec=/usr/bin/php-cgi
pidfile=/var/run/$name.pid
args="--host=$bind --admin_host=$bind --php_executable_path=$phpexec"
prog='/usr/bin/python /opt/google_appengine/dev_appserver.py'
#
# TODO: Figure out how to switch user (ie: --chuid www-data)
#
case "${1}" in
start)
echo "Starting...$desc"
start-stop-daemon --start --make-pidfile --background --oknodo \
--pidfile $pidfile \
--name $name \
--exec $prog \
-- $args $docroot
;;
stop)
echo "Stopping...$desc"
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $prog
;;
restart)
${0} stop
sleep 1
${0} start
;;
*)
echo "Usage: ${0} {start|stop|restart}"
exit 1
;;
esac
exit 0
I cannot figure out how to start the service as www-data and I am sure I could make this script more robust but for development purposes it is sufficient and runs as a daemon.
Hope this helps someone in the future,
Alex
I would like a script that does something along the lines of:
if process_name not running
start process from path /home/data/process_name
write "date: process start" to /home/data/log.txt
I have never written a bash script, and I dodn't know what to do.
On Debian and Ubuntu you can use start-stop-daemon. It has all sorts of options to help identify the right process so that you don't end up starting it twice or killing the wrong one. An example from the man page:
Start the food daemon, unless one is already running (a process named
food, running as user food, with pid in food.pid):
start-stop-daemon --start --oknodo --user food --name food --pidfile /var/run/food.pid --startas /usr/sbin/food --chuid food -- --daemon
This command makes sure that the process belongs to the right user, has the right name, and has a process id matching that in /var/run/food.pid. You don't have to use them all, of course.
Try this:
if ! pgrep process_name; then
/home/data/process_name &
echo "$(date): Process start" >> /home/data/log.txt
fi
If do you want to kill process and then start it, try this:
if ! pgrep process_name; then
/home/data/process_name &
echo "$(date): Process start" >> /home/data/log.txt
else
killall process_name
/home/data/process_name &
echo "$(date): Process start" >> /home/data/log.txt
fi
the standard upstart script that comes with mongodb works fine:
# Ubuntu upstart file at /etc/init/mongodb.conf
limit nofile 20000 20000
kill timeout 300 # wait 300s between SIGTERM and SIGKILL.
pre-start script
mkdir -p /var/lib/mongodb/
mkdir -p /var/log/mongodb/
end script
start on runlevel [2345]
stop on runlevel [06]
script
ENABLE_MONGODB="yes"
if [ -f /etc/default/mongodb ]; then . /etc/default/mongodb; fi
if [ "x$ENABLE_MONGODB" = "xyes" ]; then exec start-stop-daemon --start --quiet --chuid mongodb --exec /usr/bin/mongod -- --config /etc/mongodb.conf; fi
end script
if i want to run a second instance of mongod i thought i just copy both /etc/mongodb.conf -> /etc/mongodb2.conf and /etc/init/mongodb.conf -> /etc/init/mongodb2.conf and change the std port in the first conf-file. then adjust the script above to start with the newly created /etc/mongodb2.conf.
i can then just say start mongodb2and the service starts ... but it is killed right after starting. what do i change, to get both processes up and running?
# Ubuntu upstart file at /etc/init/mongodb2.conf
limit nofile 20000 20000
kill timeout 300 # wait 300s between SIGTERM and SIGKILL.
pre-start script
mkdir -p /var/lib/mongodb2/
mkdir -p /var/log/mongodb2/
end script
start on runlevel [2345]
stop on runlevel [06]
script
ENABLE_MONGODB="yes"
if [ -f /etc/default/mongodb ]; then . /etc/default/mongodb; fi
if [ "x$ENABLE_MONGODB" = "xyes" ]; then exec start-stop-daemon --start --quiet --chuid mongodb --exec /usr/bin/mongod -- --config /etc/mongodb2.conf; fi
end script
i couldn't get the "standard" upstart script to work (as described above), so i changed it like this:
# Ubuntu upstart file at /etc/init/mongodb.conf
limit nofile 20000 20000
kill timeout 300 # wait 300s between SIGTERM and SIGKILL.
pre-start script
mkdir -p /var/lib/mongodb/
mkdir -p /var/log/mongodb/
end script
start on runlevel [2345]
stop on runlevel [06]
script
exec sudo -u mongodb /usr/bin/mongod --config /etc/mongodb.conf
end script
and if you want to run other instances of mongodb just copy the *.conf files and make the changes to /etc/mongodb2.conf and /etc/init/mongodb2.conf
# Ubuntu upstart file at /etc/init/mongodb2.conf
limit nofile 20000 20000
kill timeout 300 # wait 300s between SIGTERM and SIGKILL.
pre-start script
mkdir -p /var/lib/mongodb2/
mkdir -p /var/log/mongodb2/
end script
start on runlevel [2345]
stop on runlevel [06]
script
exec sudo -u mongodb /usr/bin/mongod --config /etc/mongodb2.conf
end script
i think the only thing that is not working is restart mongodb - you have to stop and then start again ...
I know there's already an accepted solution but I think this one is more elegant.
The other way is to use start-stop-daemon's pid file creation. For example, I have 2 mongos running on the same server with 2 different upstart scripts, and the two magic lines are:
exec start-stop-daemon --make-pidfile --pidfile /var/run/mongodb-router.pid --start --startas /data/bin/mongos --chuid mongo -- --logappend --logpath /mnt/log/mongos.log --configdb mongo2-config01,mongo2-config02,mongo2-config03
exec start-stop-daemon --make-pidfile --pidfile /var/run/mongodb-routerrt.pid --start --startas /data/bin/mongos --chuid mongo -- --logappend --logpath /mnt/log/mongos-rt.log --configdb mongort-config01,mongort-config02,mongort-config03 --port 27027
Note that one has '--pidfile /var/run/mongodb-router.pid' and the other has '--pidfile /var/run/mongodb-routerrt.pid' and a different port.
Yeah I ran into this same issue today. The reason is that the default script uses the start-stop-daemon to start mongo, which is specifically designed to ensure that only one version of a process is running. You already figured out that one way to fix this is to not use start-stop-daemon and to start the binary yourself. That's the way I do it too but I'd be curious to hear if there's a better way.
This is how I do it.
2 instances of mongodb, with start-stop-daemon, on the same server
that are my start-stop-daemon configs
exec start-stop-daemon --make-pidfile --pidfile /var/lib/mongodb/db1.pid --start --quiet --chuid mongodb --name mongod1 --exec /usr/bin/mongod -- --config etc/mongodb1.conf
exec start-stop-daemon --make-pidfile --pidfile /var/lib/mongodb/db2.pid --start --quiet --chuid mongodb --name mongod2 --exec /usr/bin/mongod -- --config etc/mongodb2.conf
pay attention to the --name option. That did the trick for me
the two daemons cannot listen on the same tcp port, thus you have to change the --port parameter of mongod2 in order to listen to a different port.
the two daemons cannot share the same data dir, thus you have to change the --data-dir parameter of mongod2.
I find the below upstart works for me
# Ubuntu upstart file at /etc/init/mongodb.conf
description "manage mongodb instance"
start on runlevel [2345]
stop on runlevel [06]
limit nofile 20000 20000
kill timeout 300 # wait 300s between SIGTERM and SIGKILL.
env MONGODB_USER=mongodb
env MONGODB_DATA=/var/lib/mongodb/
env MONGODB_LOG=/var/log/mongodb/
env MONGODB_PID=/var/run/mongodb.pid
pre-start script
if [ ! -d $MONGODB_DATA ]; then
mkdir -p $MONGODB_DATA
chown $MONGODB_USER:$MONGODB_USER $MONGODB_DATA
fi
if [ ! -d $MONGODB_LOG ]; then
mkdir -p $MONGODB_LOG
chown $MONGODB_USER:$MOGODB_USER $MONGODB_LOG
fi
end script
exec start-stop-daemon --start --pidfile $MONGODB_PID --chuid $MONGODB_USER:$MONGODB_USER --exec /usr/bin/mongod -- --config /etc/mongodb/mongodb.conf
pre-stop exec start-stop-daemon --signal QUIT --stop --quiet --pidfile $MONGODB_PID --chuid $MONGODB_USER:$MONGODB_USER --exec /usr/bin/mongod -- --config /etc/mongodb/mongodb.conf
I have a daemon I am creating in linux. I created the init.d file and have successfully started the daemon process using
/etc/init.d/mydaemon start
When I try to stop it(with /etc/init.d/mydaemon stop), however, it stops successfully, but start-stop-daemon never seems to complete as evidenced by no echos occuring immediately after the call to start-stop-daemon
Verbose mode shows that it stopped the process, and looking at system monitor, it does stop the process.
Stopped mydaemon (pid 13292 13310).
Here is my stop function of the init.d file.
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --name $NAME -v
echo "stopped"#This is never printed and the script never formally gives shell back.
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
return "$RETVAL"
}
I am running this on virtual machine, does this affect anything?
Running on a virtual machine shouldn't affect this.
And I have no idea why this is happening or how it is taking over control of the parent script.
However, I just encountered this issue and discovered that if I do:
start-stop-daemon ... && echo -n
it will work as expected and relinquish control of the shell.
I have no idea why this works, but it seems to work.