将 curses 应用程序的输出发送到 tty1
Sending curses application's output to tty1
目标
我想让我的 curses Python 应用程序在 Linux 机器的第一个物理控制台 (TTY1) 上显示它的输出,方法是将它添加到 /etc/inittab
,用 telinit q
等等。
我想避免在从 /etc/inittab
开始时使用 IO 重定向的 hacky 方式:
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)
我已经拥有的代码可以满足我的所有需求,除了它只在 运行 来自的终端上显示输出。当在没有我上面提到的 hacky 重定向的情况下从 inittab 调用时,它可以工作,但 TTY1 上没有输出。
我知道 init 不会自行重定向输入和输出,所以这是预料之中的。
我需要如何修改现有代码才能将其输出发送到请求的 TTY 而不是 STDOUT?
PS。我不是在问如何添加对命令行参数的支持,我已经有了这个但是为了简洁起见从代码示例中删除了它。
这很简单。只需打开终端设备一次输入,一次输出;然后将输入描述符复制到活动进程的文件描述符 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
module 运行 测试了这个:
import cmd
cmd.Cmd().cmdloop()
完美运行。使用 curses 从它们的外观可以明显看出缺少某些东西:TERM
环境变量:
os.environ['TERM'] = 'linux'
在导入之前执行所有这些语句 curses
它应该可以工作。
目标
我想让我的 curses Python 应用程序在 Linux 机器的第一个物理控制台 (TTY1) 上显示它的输出,方法是将它添加到 /etc/inittab
,用 telinit q
等等。
我想避免在从 /etc/inittab
开始时使用 IO 重定向的 hacky 方式:
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)
我已经拥有的代码可以满足我的所有需求,除了它只在 运行 来自的终端上显示输出。当在没有我上面提到的 hacky 重定向的情况下从 inittab 调用时,它可以工作,但 TTY1 上没有输出。
我知道 init 不会自行重定向输入和输出,所以这是预料之中的。
我需要如何修改现有代码才能将其输出发送到请求的 TTY 而不是 STDOUT?
PS。我不是在问如何添加对命令行参数的支持,我已经有了这个但是为了简洁起见从代码示例中删除了它。
这很简单。只需打开终端设备一次输入,一次输出;然后将输入描述符复制到活动进程的文件描述符 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
module 运行 测试了这个:
import cmd
cmd.Cmd().cmdloop()
完美运行。使用 curses 从它们的外观可以明显看出缺少某些东西:TERM
环境变量:
os.environ['TERM'] = 'linux'
在导入之前执行所有这些语句 curses
它应该可以工作。