Summary: Looking for some help using a named pipe in my init.d startup script. The pipe doesn't work when it starts, and I can't figure out how to kill it.
I have this startup script that I'm using in Ubuntu 10.04 x64 to launch a minecraft server. The one thing that I need is to setup a read FIFO so that I can pass commands in to the server from the shell. I made a .fifo file and it works great if I launch the server manually from the shell as follows:
tail -f minecraft.fifo | /usr/lib/jvm/java-6-sun/bin/java -Xmx2048M -Xms2048M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=2 -XX:+AggressiveOpts -jar minecraft_server.jar &
Where I'm struggling is when I plug that tail -f minecraft.fifo in to the init script. When I start the service, the "tail -f minecraft.fifo" starts up; but it doesn't pass commands in to the minecraft server like it does when I start it manually from the shell.
Also, I'm not figuring out how to stop the named pipe. So far I figure I need to save the PID of the process and then kill that PID during stop. But I'm not figuring out how to get the PID out of $! in to a variable so that I can recall it.
Make sense? The tail doesn't work when I invoke it, and I'm not figuring out how to kill the tail process.
Here is the functioning startup script which does not contain the named pipe:
#!/bin/bash
# /etc/init.d/minecraft
### BEGIN INIT INFO
# Provides: minecraft
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start: $network
# Should-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Minecraft server
# Description: Starts the minecraft server
### END INIT INFO
#Settings
JARFILE='minecraft_server.jar'
USERNAME="minecraft"
MCHOME='/home/minecraft'
NAMEDPIPE='minecraft.fifo'
DAEMON="/usr/lib/jvm/java-6-sun/bin/java -Xmx2048M -Xms2048M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=2 -XX:+AggressiveOpts -jar $JARFILE nogui $"
ME=`whoami`
as_user() {
if [ $ME == $USERNAME ] ; then
bash -c "$1"
else
su - $USERNAME -c "$1"
fi
}
mc_start() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $JARFILE > /dev/null
then
echo "Tried to start but $JARFILE was already running!"
else
echo "$JARFILE was not running... starting."
cd $MCHOME
as_user "cd $MCHOME && screen -dmS minecraft $DAEMON"
sleep 7
if ps ax | grep -v grep | grep -v -i SCREEN | grep $JARFILE > /dev/null
then
echo "$JARFILE is now running."
else
echo "Could not start $JARFILE."
fi
fi
}
mc_stop() {
if ps ax | grep -v grep | grep -v -i SCREEN | grep $JARFILE > /dev/null
then
echo "$JARFILE is running... stopping."
as_user "screen -p 0 -S minecraft -X eval 'stuff \"say SERVER SHUTTING DOWN IN 10 SECONDS. Saving map...\"\015'"
as_user "screen -p 0 -S minecraft -X eval 'stuff \"save-all\"\015'"
sleep 10
as_user "screen -p 0 -S minecraft -X eval 'stuff \"stop\"\015'"
sleep 7
else
echo "$JARFILE was not running."
fi
if ps ax | grep -v grep | grep -v -i SCREEN | grep $JARFILE > /dev/null
then
echo "$JARFILE could not be shut down... still running."
else
echo "$JARFILE is shut down."
fi
}
#Start-Stop here
case "$1" in
start)
mc_start
;;
stop)
mc_stop
;;
restart)
mc_stop
mc_start
;;
status)
if ps ax | grep -v grep | grep -v -i SCREEN | grep $JARFILE > /dev/null
then
echo "$JARFILE is running."
else
echo "$JARFILE is not running."
fi
;;
*)
echo "Usage: /etc/init.d/minecraft {start|stop|status|restart}"
exit 1
;;
esac
exit 0
If I modify the DAEMON variable as so, the script does start it, and the tail -f can be found with a ps -ef:
DAEMON="tail -f minecraft.fifo | /usr/lib/jvm/java-6-sun/bin/java -Xmx2048M -Xms2048M -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalPacing -XX:ParallelGCThreads=2 -XX:+AggressiveOpts -jar $JARFILE nogui $"
But if I echo a command to the minecraft.fifo, the server doesn't read it. Looking at the ps, it seems the tail -f minecraft.fifo is actually starting in a separate process. That may be the problem.
Note: I'm using the SCREEN command to invoke the DAEMON because I needed a way to jump in to a running server and issue commands to it. So I just screen -r as the user minecraft and then I can work with the server. Once this fifo is working, however, I will no longer need the screen stuff. So if that's getting in the way, it can be removed.
As for killing it; if I put a killall tail in the mc_stop, it works. But that kills all tails and I have others running that I don't want to kill. So far I haven't figured out how to start the server in a way that stores the PID so that I can kill using the PID. Or to start the tail with a unique process name so that I could killall it without endangering other tails.
Any thoughts on how to start the server properly using the named pipe; and then how to properly stop it?