
Estoy intentando ejecutar un programa con una interfaz ncurse como demonio usando la pantalla. Quiero usar start-stop-daemon para administrar el proceso, pero tengo problemas para crear un script de inicio SysV.
Variables:
NAME=rtorrent
CHDIR=/opt/$NAME
DAEMON=$NAME
DAEMON_ARGS="-d -m -S $NAME $DAEMON &> /dev/null"
USER=media
GROUP=media
PIDFILE=/var/run/$NAME.pid
Actualmente, mi función de inicio es esta:
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
pgrep -F $PIDFILE > /dev/null 2>&1 || return 1
start-stop-daemon --start --quiet --make-pidfile --pidfile $PIDFILE --chuid $USER:$GROUP --chdir $CHDIR --background --exec screen -- $DAEMON_ARGS || return 2
}
Pero esto está almacenando la sleep
ID del proceso. Posiblemente, el demonio podría caer y dejar el sleep
proceso en ejecución.
Mi función de parada necesita detener ambos, entonces tengo:
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
pgrep -F $PIDFILE > /dev/null 2>&1 || return 1
for i in `ps -C $NAME -o pid=` ; do kill $i ; done
pgrep -F $PIDFILE > /dev/null 2>&1 || return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
}
Lo cual debería funcionar (aún no probado), pero con el problema de que desactivará cualquier otro proceso creado por cualquier otro usuario con $NAME
como en su nombre o argumentos.
Creo que mi solución es hacer que mi ps
función devuelva solo pids de nombres de procesos $NAME
que fueron creados por $USER
. Dado que este demonio se ejecutará con un ID de usuario dedicado.
No estoy seguro de cómo obtener este resultado. ps -C $NAME -u $USER o pid=
me da una lista para cada partido, pero quiero una lista para ambos partidos. En caso de que decida que este usuario puede manejar algún otro proceso más adelante.
Además, ¿qué pasa con la recarga?
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
¿Recargará el screen
proceso, recargará el demonio? ¿Existe una mejor manera? Cualquier ayuda es muy apreciada.
Respuesta1
Necesitaba lo mismo para un servidor Bedrock de Minecraft como demonio, pero mipatopatogo-fuNo pude encontrar una solución... finalmente armé el siguiente script de inicio.
El punto clave a tener en cuenta es que start-stop-deamon
no se utiliza para iniciar la sesión de pantalla, ejecutamos screen
endemoniomodo (separado) directamente.
#!/bin/sh
### BEGIN INIT INFO
# Provides: PocketMine-MP
# Required-Start: $network $remote_fs $local_fs
# Required-Stop: $network $remote_fs $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: PocketMine-MP (Minecraft Bedrock/PE).
# Description: PocketMine-MP (Minecraft Bedrock/PE) Server for my children and tribe.
### END INIT INFO
# Auhtor: Daniel Sokolowski <[email protected]>
# Install by typing update-rc.d <FILEsNAME> defaults
sPATH=/sbin:/usr/sbin:/bin:/usr/bin
sNAME=PocketMine-MP
sDAEMON=/usr/local/PocketMine-MP/start.sh
sDAEMON_ARGS=""
sUSER=$sNAME # can't have - in usernmae
sCONFFILE=/usr/local/PocketMine-MP/server.properties
sPIDFILE=/var/run/$sNAME.pid
sCHDIR=/var/lib/$sNAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
# Check if user exists
if ! id -u $sUSER > /dev/null 2>&1; then
echo "The user does not exist; adapt and execute below commands to create it:"
echo ""
echo "root@sh1:~# adduser --home /usr/local/$sNAME/ --shell /bin/false --no-create-home --ingroup daemon --disabled-password --disabled-login $sUSER"
echo "..."
echo "root@sh1:~# chown $sNAME:daemon /usr/local/$sNAME/ -R"
exit 1
fi
# Exit if the package is not installed
[ -x $sDAEMON ] || exit 0
# Read configuration variable file if it is present
# [ -r /etc/default/$sNAME ] && . /etc/default/$sNAME
# do_start()
# =========
# Function that starts the deamon/service
# Returns:
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
do_start() {
if ! [ -f $sCONFFILE ]; then
echo "$sNAME is not configured so not starting. Please create configuration file `$sCONFFILE`.">&2
return 2
fi
# Directory in /var/run may disappear on reboot (e.g. when tmpfs used for /var/run).
#mkdir -p $sRUNDIR
#chown -R $sUSER: $sRUNDIR
#chmod -R ug=rwX,o= $sRUNDIR
# If using `start-stop-deamon` uncomment the below and comment `screen`
<<'COMMENT' # see https://unix.stackexchange.com/questions/37411/multiline-shell-script-comments-how-does-this-work
start-stop-daemon --start --verbose --pidfile $sPIDFILE --exec $sDAEMON --name $sNAME --user $sUSER --test || return 1 # deamon is already running
start-stop-daemon --start --verbose --pidfile $sPIDFILE --exec $sDAEMON --name $sNAME --user $sUSER --chdir $sCHDIR -- $sDAEMON_ARGS $sDAEMON_OPTS || return 2 # deamon could not be started
return 0 # things worked
COMMENT
# if using screen , #NOTE,2019-feb-26: using "" after user will error out as it treats it as a "command foo - bar" command
sudo --user=$sUSER /usr/bin/screen -d -m -S $sNAME $sDAEMON $sDAEMON_ARGS
sleep 5
pgrep -f PocketMine-MP | tail -1 > $sPIDFILE
}
# do_stop()
# =========
# Function that stops the daemon/service
# Reeturns:
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
do_stop()
{
# if using start-stop-deamon
#<<'COMMENT'
#start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $sPIDFILE
start-stop-daemon --stop --verbose --retry=TERM/30/KILL/5 --pidfile $sPIDFILE
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.
rm -f $sPIDFILE
sleep 5s
return "$RETVAL"
#COMMENT
# if using `screen` for interactive programs
}
# do_reload()
# ===========
# Function that sends a SIGHUP to the daemon/service
#
# If the daemon can reload its configuration without restarting (for example, when it is sent a SIGHUP), then implement that here.
do_reload() {
# PocketMine does support SIGHUP https://github.com/PocketMine/PocketMine-MP/blob/master/src/pocketmine/Server.php#L2026
#start-stop-daemon --stop --quiet --pidfile $sPIDFILE --name $sNAME --user $sUSER --signal HUP
start-stop-daemon --stop --verbose --pidfile $sPIDFILE --name $sNAME --user $sUSER --signal HUP
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting \`$sDAEMON\` " "$sNAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping \`$sDAEMON\`" "$sNAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$sDAEMON" "$sNAME" && exit 0 || exit $?
;;
reload|force-reload)
log_daemon_msg "Reloading \`$sDAEMON\`" "$sNAME"
do_reload
log_end_msg $?
;;
restart)
log_daemon_msg "Restarting \`$sDAEMON\`" "$sNAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1|*) log_end_msg 1 ;;
esac
;;
*) log_end_msg 1 ;;
esac
;;
*)
echo "Usage: \`/etc/init.d/`basename "$0"` {start|stop|status|restart|force-reload}\`" >&2
exit 3
;;
esac
exit 0