3

現在取り組んでいる C プロジェクト用のサービス スクリプトを作成しており、起動時にいくつかのユーティリティを実行します。ログ ユーティリティを使用してすべての出力を取得したいと考えています。/etc/rc5/myscript に次のようなものがあります

#!/bin/bash    
#save fd 1 in fd 3 for use later
exec 3<&1
$SERVICESCRIPT | logger

ロガーは、EOF に達するまで標準入力から読み取るだけです。2 番目のスクリプトは、一連のユーティリティが実行されているかどうかを確認し、独自のいくつかのユーティリティを起動する場所です。これらのユーティリティの中には、フォークしてデーモン プロセスになるものがあります。スクリプトから実行しているので、すべてのスクリプト fds を継承します。これにより、スクリプトが呼び出された後、コマンド ラインに戻らなくなります。

私はいくつかの方法でこれに対抗しようとしました:

まず、デーモンプロセスを開始するスクリプトで、次のことを行いました。

(
exec 4<&-
exec 3<&-
$daemon_process
)

これにより、添え字が起動され、3 と 4 が閉じられ (それぞれ stdout とパイプ出力を格納するために使用されます)、プログラムが実行されます。しかし、コマンドラインに戻ろうとするとまだハングアップするため、パイプが閉じられていないと思われます。さらに調査すると、閉じた後にエコーを配置し、ロガーにパイプされた fd にリダイレクトすると、ログにそれらが表示され、fd が実際にまだ無傷であることがわかります。Cプログラムでfds 2-4を閉じると、コマンドラインに戻るのがわかりますが、これは非常に面倒で不快な修正です。

次に、次のことを試しました。

$daemon_process 4<&- 3<&-

プログラムを呼び出すときにfdsを閉じる必要がありますが、残念ながら、スクリプトがコマンドラインに戻らないという同じ結果が表示されます。

スクリプトが渡されたら、「CTRL-C」を押してコマンドラインに戻すことができますが、これは決して解決策ではありません.

何か案は?

ありがとう!!!!

4

2 に答える 2

0

の中に何かがあるため、あなた/etc/rc5/myscriptはブロックされていません$SERVICESCRIPT。終了するのを待っているため、ブロックされていloggerます。これは、STDIN への書き込みがすべて終了するまで行われません (この場合はデーモンです)。

この単純化された例で、この動作を確認できます。自分自身を孤立させ、永久に何もしない次の単純な C プログラムを考えてみましょう。

#include <stdlib.h>

int main( int argc, char *argv[] ){
        if( fork() ){
                exit( 0 );
        }
        while( 1 ){
                sleep( 1 );
        }
        return EXIT_SUCCESS;
}

そして、STDINからEOFまで読み取るだけのこの単純な「ロガー」:

#include <stdio.h>

int main( int argc, char *argv[] ){
        char c;
        while( 1 ){
                c = getc( stdin );
                if( c == EOF ){
                        break;
                }
        }
        return 0;
}

これらを一緒に実行すると、コマンド プロンプトが表示されなくなります。

$ ./forktest | ./logger
<hangs>

これは、シェルがパイプライン全体が終了するのを待っているためです。 forktest「終了」(それ自体を殺す)がlogger終了せず、これが私たちが待っていることです。の孤立したプロセスがforktestの STDIN を開いたままにしていますlogger。上記の実行中に別の端末をloggerチェックインすると、孤立した (その親プロセスが 1 であることに注意してください) の STDOUT (fd 1) からのパイプが STDIN (fd 0) に行くことがわかります。/proc/$pid/fd

$ ps -ef | grep forktest
cneylan  25451     1  0 16:27 pts/7    00:00:00 ./forktest
$ ps -ef | grep logger
cneylan  25450 24379  0 16:27 pts/7    00:00:00 ./logger
$ ls -l /proc/25451/fd
total 0
lrwx------ 1 cneylan cneylan 64 Jul  2 16:28 0 -> /dev/pts/7
l-wx------ 1 cneylan cneylan 64 Jul  2 16:28 1 -> pipe:[944400]
lrwx------ 1 cneylan cneylan 64 Jul  2 16:28 2 -> /dev/pts/7
lrwx------ 1 cneylan cneylan 64 Jul  2 16:28 3 -> /dev/pts/7
$ ls -l /proc/25450/fd
total 0
lr-x------ 1 cneylan cneylan 64 Jul  2 16:28 0 -> pipe:[944400]
lrwx------ 1 cneylan cneylan 64 Jul  2 16:28 1 -> /dev/pts/7
lrwx------ 1 cneylan cneylan 64 Jul  2 16:28 2 -> /dev/pts/7
lrwx------ 1 cneylan cneylan 64 Jul  2 16:28 3 -> /dev/pts/7

補足として、これが発生したときに ^C を実行すると、loggerプロセスにシグナルを送るだけです。これは、デーモンが呼び出されることになっているsetsid(2)ためです。したがって、^C がデーモンを強制終了していて、コードを呼び出す必要があるsetsid(2)か、コードが既に呼び出しsetsid(2)ていて、バックグラウンドで多数の不正なデーモンが実行されているかのいずれかです :)

于 2013-07-02T20:51:34.247 に答える
0

あなたが正しく認識しているように、のブロッキングはlogger、読み取り側と(最終的に$daemon_processは)書き込み側の間のパイプの問題です。後者の出力を画面に書き込みたいので、

$daemon_process >/dev/tty

問題を解決します。

于 2013-09-17T11:21:39.600 に答える