简体   繁体   中英

Sending curses application's output to tty1

Goal

I'd like to make my curses Python application display its output on a Linux machine's first physical console (TTY1) by adding it to /etc/inittab , reloading init with telinit q and so on.

I'd like to avoid a hacky way of using IO redirection when starting it from /etc/inittab with:

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

What I'm after is doing it natively from within my app, similar to the way getty does it, ie you use a command line argument to tell it on which TTY to listen to:

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

Example code

For simplicity, let's say I've written this very complex app that when invoked, prints some content using ncurses routines.

import curses

class CursesApp(object):

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

curses.wrapper(CursesApp)

The code I already have does everything I need, except that it only shows its output on the terminal it's run from. When invoked from inittab without the hacky redirection I mentioned above, it works but there's no output on TTY1.

I know that init doesn't redirect input and output by itself, so that's expected.

How would I need to modify my existing code to send its output to the requested TTY instead of STDOUT?

PS. I'm not asking how to add support for command line arguments, I already have this but removed it from the code sample for brevity.

This is rather simple. Just open the terminal device once for input and once for output; then duplicate the input descriptor to the active process' file descriptor 0, and output descriptor over file descriptors 1 and 2. Then close the other handles to the 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)

I tested this with the cmd module running on TTY6:

import cmd
cmd.Cmd().cmdloop()

Works perfectly. With curses it is apparent from their looks that something is missing: TERM environment variable:

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

Execute all these statements before even importing curses and it should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM