努力弄清楚如何通过这个 init.d 启动脚本使用 FIFO
摘要:在我的 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 手动启动它时那样将命令传递到我的世界服务器。
另外,我不知道如何停止命名管道。到目前为止,我认为我需要保存进程的 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,因为我需要一种方法来跳转到正在运行的服务器并向其发出命令。因此,我只需以“minecraft”用户身份筛选 -r,然后就可以使用服务器了。然而,一旦这个 fifo 工作起来,我就不再需要屏幕了。因此,如果它妨碍了,可以将其删除。
至于杀掉它;如果我在 mc_stop 中添加一个killall tail,它就会起作用。但这会杀死所有尾巴,而我还有其他我不想杀死的尾巴。到目前为止,我还没有弄清楚如何以存储 PID 的方式启动服务器,以便我可以使用 PID 进行杀死。或者以唯一的进程名称开始尾部,以便我可以杀死所有尾部而不危及其他尾部。
关于如何使用命名管道正确启动服务器的任何想法;那么如何正确阻止呢?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
要从 shell 通过命名管道 (fifo) 向服务器发送命令,请参阅此处:
重定向应用程序(java)的输入,但仍然允许 BASH 中的 stdin
如何在脚本中使用 exec 3>myfifo,而不让 echo foo>&3 close管道?
For sending commands to the server via a named pipe (fifo) from the shell see here:
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?
好吧,我只是捂着脸,意识到我不需要使用 fifo,因为我已经使用 SCREEN 通过 mc_stop 将命令传递给它。 (我没有写启动脚本,我只是想调整它,所以不太熟悉它)
screen -p 0 -S minecraft -X eval 'stuff \" 说服务器在 10 秒内关闭。保存地图...\"\015'"
这正是我想要使用 fifo 的目的。
所以……这个问题已解决。
非常感谢您的帮助。我确实尝试使用该脚本并且它起作用了,但它也做了一些非常奇怪的事情,它成功地将命令发送到 fifo 但随后它进入了一个奇怪的循环并向服务器发送了某种空命令。服务器识别出第一个命令,然后开始回显“未识别到哪个命令”是一个谜,因为它不在日志中,也没有显示在我的世界控制台中,但是,我将继续使用您的命令。脚本,以便我可以进一步理解 fifo 的。我试图对您的回复表示赞赏,但 stackexchange 告诉我,我还没有足够高的声誉。所以如果其他人可以投票给我的话;请。
Ok I just facepalmed and realized that I don't need to use a fifo since I'm already using SCREEN to pass commands in to it through the mc_stop. (I didn't write the startup script, I'm just trying to tweak it, so not intimately familiar with it)
screen -p 0 -S minecraft -X eval 'stuff \"say SERVER SHUTTING DOWN IN 10 SECONDS. Saving map...\"\015'"
That accomplished exactly what I wanted to use the fifo for.
SO...mine was a stupid question. This issue is resolved.
@pepoluan; thanks very much for helping. I really appreciate the response. I did attempt to use the script and it worked, but it also did something very strange. It successfully sent the command to the fifo. But then it went in to a strange loop and sent some sort of null command to the server. The server recognized the first command and then started echoing "command not recognized". What command was not recognized is a mystery, as it isn't in the logs and did not display in the minecraft console. I will, however, continue working with your script so that I can further understand fifo's. I attempted to vote up your response in appreciate but stackexchange told me that I didn't have a high enough reputation yet. So if someone else could vote him up for me; please.
为什么不运行监视 FIFO 命名管道的脚本,而不是使用
tail -f
?使用
scriptname.sh
进行测试,如果您喜欢,请使用scriptname.sh | 启动它。无论_commands_here
。或者甚至是 nohup scriptname.sh | whatever_commands &.将信号
there is no place like home\n
发送到命名管道,scriptname.sh
应该正常结束。(我希望我没有误解你的问题。)
Rather than using
tail -f
, why not run a script monitoring the FIFO named pipe?Test it using
scriptname.sh
, and if it's to your liking, prime it withscriptname.sh | whatever_commands_here
. Or evennohup scriptname.sh | whatever_commands &
.Send the signal
there is no place like home\n
to the named pipe andscriptname.sh
should end gracefully.(I hope I didn't misunderstand your problem.)