努力弄清楚如何在这个init.d启动脚本中使用FIFO

时间:2011-05-05 06:01:18

标签: bash shell ubuntu-10.04 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手动启动它时那样将命令传递给我的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终止。或者使用一个独特的流程名称启动尾部,这样我就可以在不危及其他尾部的情况下解决问题。

关于如何使用命名管道正确启动服务器的任何想法;然后如何正确阻止它?

3 个答案:

答案 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)

答案 2 :(得分:0)

好吧,我只是面对面并意识到我不需要使用fifo,因为我已经使用SCREEN通过mc_stop将命令传递给它。 (我没有写启动脚本,我只是想调整它,所以不要非常熟悉它)

屏幕-p 0 -S minecraft -X eval'东西\“说服务器在10秒内关闭。保存地图...... \”\ 015'“

这完全符合我想要使用的fifo。

所以...我的是一个愚蠢的问题。此问题已得到解决。

@pepoluan;非常感谢你的帮助。我非常感谢你的回应。我确实尝试使用该脚本并且它有效,但它也做了一些非常奇怪的事情。它成功地将命令发送到fifo。但后来它进入了一个奇怪的循环,并向服务器发送了一些null命令。服务器识别出第一个命令,然后开始回显“命令未识别”。什么命令未被识别是一个谜,因为它不在日志中并且没有显示在我的世界控制台中。但是,我将继续使用您的脚本,以便我可以进一步了解fifo。我试图投票赞成你的回应,但是stackexchange告诉我,我的声誉还不够高。所以,如果有其他人可以为我投票;请。