2

ゴール

/etc/inittabcurses Python アプリケーションの出力を Linux マシンの最初の物理コンソール (TTY1) に追加したり、init をリロードしたりして出力したいと考えていtelinit qます。

次から開始するときに、IOリダイレクトを使用するハックな方法を避けたいと思い/etc/inittabます。

1:2345:respawn:/path/to/app.py > /dev/tty1 < /dev/tty1

私が求めているのは、アプリ内からネイティブに実行する方法gettyです。つまり、コマンド ライン引数を使用して、リッスンする TTY を指定します。

S0:2345:respawn:/sbin/getty -L ttyS1 115200 vt100

サンプルコード

簡単にするために、呼び出し時に ncurses ルーチンを使用して一部のコンテンツを出力する、この非常に複雑なアプリを作成したとします。

import curses

class CursesApp(object):

  def __init__(self, stdscr):
    self.stdscr = stdscr
    # Code producing some output, accepting user input, etc.
    # ...    

curses.wrapper(CursesApp)

私が既に持っているコードは、実行元の端末に出力を表示するだけであることを除いて、必要なことはすべて実行します。上記のハック リダイレクションなしで inittab から呼び出すと、機能しますが、TTY1 に出力がありません。

init はそれ自体で入力と出力をリダイレクトしないことを知っているので、それは予想通りです。

STDOUT ではなく要求された TTY に出力を送信するには、既存のコードをどのように変更する必要がありますか?

PS。コマンド ライン引数のサポートを追加する方法を尋ねているわけではありません。これは既に持っていますが、簡潔にするためにコード サンプルから削除しました。

4

1 に答える 1

2

これはかなり単純です。端末デバイスを入力用に 1 回、出力用に 1 回開くだけです。次に、入力記述子をアクティブなプロセスのファイル記述子 0 に複製し、出力記述子をファイル記述子 1 および 2 に複製します。次に、TTY への他のハンドルを閉じます。

import os
import sys

with open('/dev/tty6', 'rb') as inf, open('/dev/tty6', 'wb') as outf:
    os.dup2(inf.fileno(), 0)
    os.dup2(outf.fileno(), 1)
    os.dup2(outf.fileno(), 2)

TTY6で実行されているcmdモジュールでこれをテストしました:

import cmd
cmd.Cmd().cmdloop()

完璧に動作します。curses を使用すると、見た目から何かが欠けていることが明らかです:TERM環境変数:

os.environ['TERM'] = 'linux'

インポートする前にこれらすべてのステートメントを実行するcursesと、機能するはずです。

于 2016-03-19T14:50:14.457 に答える