0

概要: init.d 起動スクリプトで名前付きパイプを使用する方法を探しています。起動時にパイプが機能せず、それを殺す方法がわかりません。

Minecraft サーバーを起動するために Ubuntu 10.04 x64 で使用しているこの起動スクリプトがあります。シェルからサーバーにコマンドを渡すことができるように、読み取り FIFO をセットアップする必要があります。.fifo ファイルを作成しました。次のようにシェルからサーバーを手動で起動すると、うまく機能します。

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 &

私が苦労しているのは、そのテール -f minecraft.fifo を init スクリプトにプラグインするときです。サービスを開始すると、「tail -f minecraft.fifo」が起動します。しかし、シェルから手動で起動したときのように、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 変数をそのように変更すると、スクリプトはそれを開始し、末尾 -f は 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 $"

しかし、コマンドを minecraft.fifo にエコーすると、サーバーはそれを読み取りません。ps を見ると、実際には tail -f minecraft.fifo が別のプロセスで開始されているようです。それが問題かもしれません。

注: 実行中のサーバーにジャンプしてコマンドを発行する方法が必要だったため、SCREEN コマンドを使用して DAEMON を呼び出しています。したがって、ユーザー minecraft として -r をスクリーニングするだけで、サーバーを操作できます。ただし、この fifo が機能するようになると、画面の要素は必要なくなります。それで邪魔になったら取り外せます。

殺すのもよし。mc_stop に killall テールを配置すると、機能します。しかし、それはすべての尾を殺し、私は殺したくない他のものを実行しています。これまでのところ、PID を使用して強制終了できるように、PID を格納する方法でサーバーを起動する方法を理解していません。または、テールを一意のプロセス名で開始して、他のテールを危険にさらすことなくすべてを強制終了できるようにします。

名前付きパイプを使用してサーバーを適切に起動する方法についての考え; そして、それを適切に停止する方法は?

4

3 に答える 3

1

シェルから名前付きパイプ(fifo)を介してサーバーにコマンドを送信するには、次を参照してください。

アプリケーション(java)の入力をリダイレクトしますが、BASHでstdinを許可します

スクリプトでexec3>myfifoを使用し、echo foo>&3でパイプを閉じないようにするにはどうすればよいですか?

于 2011-05-05T13:51:16.017 に答える
1

を使用するtail -fのではなく、FIFO 名前付きパイプを監視するスクリプトを実行してみませんか?

#!/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正常に終了する必要があります。

(あなたの問題を誤解していないことを願っています。)

于 2011-05-05T06:29:55.547 に答える
0

さて、私は顔をしかめ、fifoを使用する必要がないことに気付きました。これは、すでにSCREENを使用してmc_stopを介してコマンドを渡すためです。(私はスタートアップスクリプトを書きませんでした、私はそれを微調整しようとしているだけなので、それをよく知っていません)

screen -p 0 -S minecraft -X eval'stuff \ "say SERVER SHUTTING DOWN IN10SECONDS。Savingmap... \" \ 015' "

それは私がFIFOを使用したかったことを正確に達成しました。

だから...私のものはばかげた質問でした。この問題は解決されました。

@pepoluan; 助けてくれてありがとう。本当にありがとうございました。私はスクリプトを使おうとしましたが、それは機能しましたが、それはまた非常に奇妙なことをしました。コマンドをFIFOに正常に送信しました。しかし、その後、奇妙なループに入り、ある種のnullコマンドをサーバーに送信しました。サーバーは最初のコマンドを認識し、「コマンドが認識されませんでした」というエコーを開始しました。ログに記録されておらず、Minecraftコンソールに表示されなかったため、認識されなかったコマンドは謎です。ただし、FIFOをさらに理解できるように、引き続きスクリプトを使用します。私は感謝の気持ちであなたの回答に投票しようとしましたが、stackexchangeは私がまだ十分な評判を持っていないと私に言いました。ですから、誰か他の人が彼を私に投票してくれるなら、お願いします。

于 2011-05-07T04:20:46.373 に答える