总结:在我的init.d启动脚本中寻找使用命名管道的一些帮助。管道在启动时不起作用,我无法弄清楚如何杀死它。
我有这个启动脚本,我在Ubuntu 10.04 x64中使用它来启动一个Minecraft服务器。我需要做的一件事是设置一个读FIFO,以便我可以从shell将命令传递到服务器。我创建了一个.fifo文件,如果我从shell手动启动服务器,它的工作原理很好:
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 &
我在努力的地方就是将tail -f minecraft.fifo插入到init脚本中。当我启动服务时,“tail -f minecraft.fifo”启动;但它不会像在我从shell手动启动它时那样将命令传递给我的Minecraft服务器。
另外,我不知道如何停止命名管道。到目前为止,我想我需要保存进程的PID,然后在停止期间终止该PID。但我不知道如何从$中取出PID!转到一个变量,以便我可以回想起它。
有意义吗?当我调用它时,尾部不起作用,我不知道如何杀死尾部过程。
这是正常运行的启动脚本,它不包含命名管道:
#!/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
如果我这样修改DAEMON变量,脚本会启动它,并且可以使用ps -ef找到tail -f:
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 $"
但是,如果我向minecraft.fifo回显命令,则服务器不会读取它。看看ps,似乎tail -f minecraft.fifo实际上是在一个单独的进程中启动的。这可能是问题所在。
注意:我正在使用SCREEN命令来调用DAEMON,因为我需要一种方法来跳转到正在运行的服务器并向其发出命令。所以我只是屏幕-r作为用户我的世界,然后我可以使用服务器。然而,一旦这个fifo正在工作,我将不再需要屏幕内容。所以,如果它阻碍了它,它就可以被移除。
至于杀死它;如果我把一个killall尾巴放在mc_stop中,它就可以了。但这会杀死所有的尾巴,而我还有其他人在跑,我不想杀人。到目前为止,我还没有想出如何以存储PID的方式启动服务器,以便我可以使用PID终止。或者使用一个独特的流程名称启动尾部,这样我就可以在不危及其他尾部的情况下解决问题。
关于如何使用命名管道正确启动服务器的任何想法;然后如何正确阻止它?
答案 0 :(得分:1)
为什么不运行监控FIFO命名管道的脚本?
,而不是使用tail -f
#!/bin/bash
NAMEDPIPE="/path/to/minecraft.fifo"
STOP_NOW="no"
STOP_SIGNAL="there is no place like home"
DELAY="1s"
while [[ $STOP_NOW == "no" ]]; do
read INCOMING_THINGS
if [[ $STOP_SIGNAL == "$INCOMING_THINGS" ]]; then
STOP_NOW="yes"
else
printf "%s\n" "$INCOMING_THINGS"
sleep $DELAY
fi
done < $NAMEDPIPE
exit 0
使用scriptname.sh
对其进行测试,如果符合您的喜好,则使用scriptname.sh | whatever_commands_here
填充它。甚至是nohup scriptname.sh | whatever_commands &
。
将信号there is no place like home\n
发送到命名管道,scriptname.sh
应该正常结束。
(我希望我没有误解你的问题。)
答案 1 :(得分:1)
要通过shell中的命名管道(fifo)向服务器发送命令,请参见:
Redirecting input of application (java) but still allowing stdin in BASH
How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?
答案 2 :(得分:0)
好吧,我只是面对面并意识到我不需要使用fifo,因为我已经使用SCREEN通过mc_stop将命令传递给它。 (我没有写启动脚本,我只是想调整它,所以不要非常熟悉它)
屏幕-p 0 -S minecraft -X eval'东西\“说服务器在10秒内关闭。保存地图...... \”\ 015'“
这完全符合我想要使用的fifo。
所以...我的是一个愚蠢的问题。此问题已得到解决。
@pepoluan;非常感谢你的帮助。我非常感谢你的回应。我确实尝试使用该脚本并且它有效,但它也做了一些非常奇怪的事情。它成功地将命令发送到fifo。但后来它进入了一个奇怪的循环,并向服务器发送了一些null命令。服务器识别出第一个命令,然后开始回显“命令未识别”。什么命令未被识别是一个谜,因为它不在日志中并且没有显示在我的世界控制台中。但是,我将继续使用您的脚本,以便我可以进一步了解fifo。我试图投票赞成你的回应,但是stackexchange告诉我,我的声誉还不够高。所以,如果有其他人可以为我投票;请。