プロセスに出力を送信するシェルスクリプトを作成する方法


11

現在、サーバーコンソールプログラムを画面で実行しています。これは、それを読んだり、時々コマンドを送信したりする必要があるためです。

アプリをバックグラウンドでデーモンとして実行したい(initで起動/停止)。

tail -fログを記録することはできましたが、それではプロセスに入力を送信できません。

入力を読み取り、送信できるように設定する方法はありますか?それでもバックグラウンドで実行していますか?

また、さまざまなプロセスからデーモンへの入力を送信できるようにもしたいと思います(たとえば、「Stop \ n」コマンドを送信できるシェルスクリプト)。


これを読みに来た人への単なるコメント-ここでの答えは素晴らしいです。名前付きパイプについて知らない場合は、少なくとも試してみることを強くお勧めします。これを使用して、Minecraftをサービスとして実行し、名前付きパイプに書き込むことで他のスクリプトからコンソールとやり取りすることができるため、出力ログを解析しながら、サーバーを停止したり、ユーザーにメッセージを送信したりするスクリプトを書くことが可能になります。重要な行を探す(たとえば、ユーザー宛のチャットメッセージをテキストとして彼に送信するなど)
Bill K

回答:


9

パイプから読み取り、ファイルに書き込む

デーモンが任意のプロセスによって生成された入力を読み取るようにするには、そのプロセスをパイプに接続する必要があります。ここで、任意のプロセスとはコマンドをエコーすることであり、それは別のコンテキストで実行されます。名前付きパイプを作成します(UNIXのコンテキストではfifoと呼ばれることが多い)。

mkfifo /var/run/daemon.fifo
</var/run/daemon.fifo /path/to/daemond --option >daemon.log

そしてパイプにコマンドを書くだけです:

echo 'FORWARD 10' >/var/run/daemon.fifo
echo 'LEFT 72' >/var/run/daemon.fifo

ただし、これがそのまま機能する可能性はほとんどありません。デーモンが標準入力でファイルの終わりを検出すると、デーモンが終了する可能性が高くなります。これは、パイプに書き込む最初のプロセスが終了するとすぐに発生します。このtail -f問題を回避するために使用できます。

</var/run/daemon.fifo tail -c +1 -f | {
  echo $$ >/var/run/daemon.pid
  exec /path/to/daemond --option >daemon.log
}

一部のtail実装では、バッファリングによって噛み付かれる可能性があります。tailプロセスは、出力を送信するのに十分なバイトを確保するまで待機します。これはPOSIXツールボックスでは解決できないと思います。それが問題である場合は、簡単なC、Perl、またはPythonプログラムを使用してください。私が知る限り、tail(Linuxや他の場所で見られるような)GNU coreutilsはこの点で安全です。

デーモンを停止するecho >/var/run/daemon.fifoと、tailプロセスが強制終了されます。


画面内でプログラムを起動する

サービスマネージャーから直接デーモンを呼び出す代わりに(本当にSysV initだけを使用しているか、ラッパースクリプトやUpstartなどの追加機能を使用していますか?)、

screen -c daemon.screenrc -L -d -m -S daemon_name /path/to/daemond --option

デーモンはサービスマネージャの子プロセスにはならないため、正しいプロセスにシグナルを送信する必要があります。それを行う方法は、デーモンがどのように開始され、どのように開始されるかによって異なります。

それはだ技術的には可能端末に実行中のプロセスをアタッチするが、これは生産システムのために外に間違いなくあるので、あなたは、プログラムがクラッシュしますリスクがあります。

この-Lオプションは、画面にウィンドウに表示されるすべてのものをファイルに書き込みます。ファイル名はで与えられているdaemon.screenrcとのlogfile指示。


実際、スクリプトからstdinにメッセージを送信できるようにしたいのですが、たぶんそれが私が尋ねるべき問題だったのでしょう。現在、私はスクリプトからサーバーを実行しているだけで、ターミナルでサーバーに入力できますが、サービスとして実行されているように見えます...
Bill K

@ビル:わかりました。次に、最初に頭に浮かぶのは名前付きパイプです。
Gilles「SO-悪をやめる」

これがまさに私が望んでいる@Gillesだと思います!私はそれをもっとよく理解する必要があります。私はそれを理解するためにマニュアルページを並べ替えるのに少し時間を費やします-私は正直にそれのほとんどを取得しません(私はあなたがしていることのほとんどを取得し、あなたがそれをどのようにしたかはほとんどありません-そして私は一種の私の理論は、プロセスに直接接続するのではなく、元のコンソールが実行されているように見えるようにするために、デーモンとのi / oを結合するさらに別のスクリプトを作成することでした。同時に別のスクリプトからエコー 'FORWARD 10'を実行します。
Bill K

私はそれの多くを得ていると思います。分解すると、「mkfifo pipe」と「tail -f pipe | command> output」を理解し、それらをテストして機能するようになりました。あなたが持っていた他のほとんどのものは、それを1つのラインで実行させるためのトリックだったと思います-重要なものを私は見逃していますか?
Bill K

@Bill:画面の外側から(画面のstuffコマンドを使用して)端末の内側に書き込むことができます。ただし、ここでは端末のオーバーヘッド(処理、ただし最も重要な認識機能)は必要ありません。パイプでほぼ十分です(ファイルの終わりを無視する小さなリレープロセスで十分です)。ある端末で、<fifo catまたは別の端末<fifo tail -f | catで少し実験したいと思うかもしれませんecho >fifo; echo >fifo。大丈夫だと思います。
Gilles「SO-邪悪なことをやめなさい」
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.