私は次のように動作するリモートttyツール(「rt」と呼ばれる)を書いています。
[rt client(rtc)] <---> [rt gateway(rtg)] <---> [rt server(rts)]
rts
NATファイアウォールの背後にあるホストはどこで実行され、rt
に/etc/rc.local
接続されますrtg
。 rtsに接続したいときにrtc
コンピュータでrtを実行すると、接続されてからrtg
要求が送信されますrts
。プログラムはTTYから始まりrt
ます。/usr/bin/login
rtc
rts
私の問題は、リモート端末でいくつかのコマンドを実行してexit
bashを終了するように入力すると、ローカル端末のプロンプトに戻りたいのですが、ほとんどいつも停止して空の画面が表示されることです。とは別にbashコマンドのみを実行し、リモートセッションで外部プログラムを実行しない場合。
編集する:
外部プログラムが何であるかを正確に定義することはやや困難です。プログラムに「デーモン」がなければ、「内部」とみなされるような気がします。つまり、背中を実行してもかまいませんが、コマンドラインのls
末尾cp
でvi
を&
使用してサービスプログラムを実行すると、rt
終了時に中断されます。
いくつかの調査をしてみましたが、残念ながら問題を一文で説明することは困難です。私が見つけることができる最も関連性の高いリソースは次のとおりです。
ターミナルエミュレータがシャットダウンするとシェルもシャットダウンされるのはなぜですか?
どこかに送れば役に立つと思いますが、SIGHUP
どうですか?どのプログラムが送信者であり、どのプログラムが受信者ですか?
答え1
説明する動作は、TTY(つまり、リモート端末の出力)から読み取り、EOFが取得されるまで読み続け(必要な場合は待機)、コントローラソフトウェアの一般的な動作です。しかし、pseudo-ttyはパイプと同じです。読み取りプロセスは、書き込みのために開かれたすべてのプロセスが閉じられるまでEOFを取得しません。 (プロセスが終了すると、開いているすべてのファイルが閉じます。)
ただし、標準出力と標準エラーをリダイレクトしない限り、非同期プロセスは stdout と stderr に書き込むために tty を開いたままにします。nohup
主な機能は中断(HUP)信号を無視することですが、補助機能はstdoutとstderrがttyを指さないようにすることです。 >
出力ストリームをリダイレクトするために(またはそのバリアント)を使用する場合は、そのままにしてもかまいませ2>
んnohup
。ただし、出力をリダイレクトしないnohup
場合 nohup.out
。
長い話を短く stdoutとstderrをリダイレクトせずに(安全のためにstdinもリダイレクトせずに)非同期コマンドを実行すると、シェルを終了すると、すべてのバックグラウンドプロセスが参照するファイル記述子をrt
閉じるまでプログラムは終了しません。ディ。実際、これはバックグラウンドプロセスが終了するのを待つことを意味します。
私がビューに「簡単で明確な」解決策は、子プロセスが終了したときに終了するようにプログラムを変更することです。ユーザー(つまり、ユーザー)がログインしたときに取得する対話型シェルプロセス
同じプロセスです。あなたが始めたように/usr/bin/login
。私はあなたがfork()
and exec()
(またはそのバリエーション)を使ってこれを行うことを望みます。したがって、PIDを追跡して呼び出しwait()
(またはそのバリアント)するだけです。
メモ:
- 疑似TTYから同時に読み取る間にシェルが終了するのを待つには、複数のプロセスまたは少なくとも複数のスレッドを使用する必要があります。
nc
(netcat
)、 、 など すでにこのような状況を処理するプログラムがたくさんあり、sshd
その一部はオープンソースであると確信しています。これを確認して、いくつかのアイデア(およびいくつかのコード)を得ることができます。wait()
考慮すべき機能の1つは、rt
TTY出力バッファで例外を処理するために終了する前に、戻ってから数秒待機することです。上記のいくつかのプログラムがこれを行うことができることがわかります。