A bit like tee, a bit like script, but all with a fake tty. Lets you remote control and watch a process

Related tags

Command-line teetty
Overview

teetty

Build Status Crates.io License rustc 1.60.0

teetty is a wrapper binary to execute a command in a pty while providing remote control facilities.

This allows logging the stdout of a process to a file, without the output being any different from if you were not to pass it through teetty. From the perspective of the program, it's connected to a terminal. At the same time however teetty multiplexes the output into both terminal and an optional log file and it also lets you send input remotely into the program while the user's keyboard is still attached. The underlying functionality is available in the tty-spawn crate.

$ cargo install teetty

Example

In one terminal we tell teetty to create and connect to a new FIFO named stdin, write the output into a file named stdout and spawn a python process.

$ teetty --in ./stdin --out ./stdout -- python
Python 3.8.12 (default, Mar  3 2022, 14:54:16)
[Clang 13.0.0 (clang-1300.0.29.30)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

We can duplex the output by watching the stdout file with tail -f in another window:

$ tail -f ./stdout
Python 3.8.12 (default, Mar  3 2022, 14:54:16)
[Clang 13.0.0 (clang-1300.0.29.30)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

In yet another window we can now remote control this python process and observe the output both in the original process as well as the window where we have tail running:

$ echo 'import sys' > ./stdin
$ echo 'print(sys.version_info)' > ./stdin
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=8, micro=12, releaselevel='final', serial=0)

Script Mode

By default teetty opens a pty and connects it to the application. Due to how pseudo terminals work stdout and stderr will be merged together. In this mode the terminal will be placed in raw mode which means that applications like Vim that want to move cursors around will function correctly.

teetty provides a second mode called "script mode" that can be enabled with --script-mode. In that mode stdout and stderr stay separated. This is accomplished by leaving stdout connected to the pseudo terminal and by connecting stderr to a secondary internal pty. Because this is a setup that execuables are not familiar with it causes all kinds of visual artifacts when raw mode is enabled. To combat this, in this mode pagers and raw mode are automatically disabled.

Note on stream synchronization: unfortunately stdout/stderr currently are not propertly synchronized in script mode. See #6 for more information.

FIFOs, Flushing and Control Characters

It's generally assumped that the --in path is a FIFO but it's possible for this to be pointed to a file just as well. For the --out parameter there is a significant difference between it being a FIFO or a file. If it's pointed to a FIFO then the writes will block immediately until someone starts reading from it (eg with cat). On the other hand if it's pointed to a file, then tail -f can be used to read from it as it happens, but old data will accumulate in the output file.

Out of the box the output is flushed constantly, but this can be disabled by passing the --no-flush flag.

The connected standard input is connected to a terminal. This means that control sequences can be sent in via the FIFO. For instance sending \x04 to the process will try to end it:

echo -n $'\004' > ./stdin

Related Projects

These are some related projects:

  • faketty: emulates two fake ttys to retain stdout and stderr. This is similar to teetty in --script-mode.
  • script: a built-in tool into most unices which can capture output of terminals.
  • tmux: emulates an entire terminal including drawing surface and more. Lets you detach and reattach to multiple terminal sessions.
  • expect: lets you script interactive command line utilities. Variations of this tool exist for programming languages like pexpect for Python.

License and Links

Comments
  • teetty passthrough SIGWINCH support

    teetty passthrough SIGWINCH support

    It would be really awesome if teetty would passthrough the SIGWINCH signal to the inferior pty. i.e. capture the SIGWINCH signal sent to teetty and send it to the inferior process of the teetty pty. Or perhaps this is the job of another utility to proxy signals.

    Even tcl/expect does not support this, to my knowledge.

    http://www.rkoucha.fr/tech_corner/sigwinch.html

    Example of resizing inside and out of teetty:

    https://asciinema.org/a/548055

    bug 
    opened by mullikine 4
  • ✏️ Fix typo in README

    ✏️ Fix typo in README

    ✏️ Fix typo in README

    Summary: In the example, stdout is redirected to ./stdout

    Test Plan: N/A


    Stack created with Sapling. Best reviewed with ReviewStack.

    • -> #1
    opened by vegerot 1
  • Using a FIFO for stdin often results in Resource temporarily unavailable

    Using a FIFO for stdin often results in Resource temporarily unavailable

    Using a FIFO for stdin often results in Resource temporarily unavailable.

    On the other hand, the problem goes away when using a plain text file for --in.

    mkfifo /tmp/stdin
    teetty --in /tmp/stdin --out /tmp/stdout -- python
    echo "import os" >> /tmp/stdin
    
    Python 3.8.2 (default, Sep  2 2022, 20:24:00)
    [GCC 8.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os
    >>> import os
    >>> import os
    >>> import os
    >>> import os
    >>> teetty: Resource temporarily unavailable (os error 11)
    

    Demonstration:

    https://asciinema.org/a/547789

    opened by mullikine 0
  • Fails to compile when installed using cargo

    Fails to compile when installed using cargo

    I am using rustc 1.65.0 (Fedora 1.65.0-1.fc37)

    cargo install teetty results in

    error[E0432]: unresolved import `std::os::fd::AsRawFd`
     --> /home/francis/.cargo/registry/src/github.com-1ecc6299db9ec823/teetty-0.1.0/src/spawn.rs:4:5
      |
    4 | use std::os::fd::AsRawFd;
      |     ^^^^^^^^^^^^^^^^^^^^ no `AsRawFd` in `os::fd`
    
    error[E0603]: module `fd` is private
     --> /home/francis/.cargo/registry/src/github.com-1ecc6299db9ec823/teetty-0.1.0/src/spawn.rs:4:14
      |
    4 | use std::os::fd::AsRawFd;
      |              ^^ private module
      |
    note: the module `fd` is defined here
    
    error[E0599]: no method named `as_raw_fd` found for reference `&&mut File` in the current scope
       --> /home/francis/.cargo/registry/src/github.com-1ecc6299db9ec823/teetty-0.1.0/src/spawn.rs:163:31
        |
    163 |             read_fds.insert(f.as_raw_fd());
        |                               ^^^^^^^^^ method not found in `&&mut File`
        |
        = help: items from traits can only be used if the trait is in scope
    help: the following trait is implemented but not in scope; perhaps add a `use` for it:
        |
    1   | use std::os::unix::io::AsRawFd;
        |
    
    error[E0599]: no method named `as_raw_fd` found for mutable reference `&mut &mut File` in the current scope
       --> /home/francis/.cargo/registry/src/github.com-1ecc6299db9ec823/teetty-0.1.0/src/spawn.rs:192:36
        |
    192 |             if read_fds.contains(f.as_raw_fd()) {
        |                                    ^^^^^^^^^ method not found in `&mut &mut File`
        |
        = help: items from traits can only be used if the trait is in scope
    help: the following trait is implemented but not in scope; perhaps add a `use` for it:
        |
    1   | use std::os::unix::io::AsRawFd;
        |
    
    Some errors have detailed explanations: E0432, E0599, E0603.
    For more information about an error, try `rustc --explain E0432`.
    error: could not compile `teetty` due to 4 previous errors
    

    Excited to use this once I can compile! It exactly solves a problem I have been struggling to address with fd redirection in Bash alone.

    opened by erik-overdahl 0
  • Find solution for ECHO

    Find solution for ECHO

    At the moment ECHO is turned off which is not intended and also does not match the behavior of the screencast. The reason for this is that when ECHO is enabled there are platform differences about whether ^D also shows up. On linux apparently it doesn't and on macOS it does. I intend on turning ECHO back on out of the box (except in script mode potentially) and to figure out what to do with these differences.

    opened by mitsuhiko 1
  • teetty maxes out its CPU core

    teetty maxes out its CPU core

    The CPU core is being maxed out after sending input to teetty.

    I assume it is polling the file which is responsible. It would be nice to eliminate the CPU usage using inotify.

    On Linux, the GNU coreutils version of tail uses inotify to block waiting for changed to the file. With FreeBSD, tail uses kevent to do the same. This will be better than repeatedly checking for changes and sleeping.

    https://asciinema.org/a/548071

    bug 
    opened by mullikine 1
  • Improve EOF Handling on Stdin

    Improve EOF Handling on Stdin

    The handling of stdin with multiplexed streams is a bit weird. It works in that the in file attached basically cannot really close the stream unless it sends ^D in, but it now also means that if the regular stdin closes (eg: it's connected to /dev/null) you end up with ^Dmore-input-here.

    One would expect that hitting the end of the attached stdin does not necessarily send ^D in that case until the other stream also closes. However that stream today cannot close. I believe the behavior is best to be controlled with some flags.

    opened by mitsuhiko 0
  • stdout/stderr desync in script mode

    stdout/stderr desync in script mode

    Today stderr and stdout end up highly desynchronized if they are used in script mode. I believe that this is generally an unsolvable issue however faketty does not appear to have this issue despite it having separate streams. I believe that the fact that stderr appears as a tty there changes something in how tools print.

    enhancement 
    opened by mitsuhiko 1
Owner
Armin Ronacher
Software developer and Open Source nut. Creator of the Flask framework. Engineering at @getsentry. Other things of interest: @pallets and @rust-lang
Armin Ronacher
Sero is a web server that allows you to easily host your static sites without pain. The idea was inspired by surge.sh but gives you full control.

sero Lightning-fast, static web publishing with zero configuration and full control ?? Table Of Contents ?? Table Of Contents ?? Tools ❓ About The Pro

Dmitry Miasnenko 6 Nov 13, 2023
A program to share a TTY like a GPS UART between 2 processes.

TTYTEE - A process that exposes 2 copies of the same TTY. The initial use case for this crate has been sharing a single GPS device talking through an

Skyways 4 Jun 25, 2023
Fast KubeJS script manager. Includes version control and compatibility with KJSPKG packages.

CarbonJS A KubeJS script manager Features ?? Super fast ⚙️ Version control ?? Constantly new scripts being added ✅ Easy to use ?? Compatibility with K

Krzysztof Poręba 3 May 9, 2023
Remote-Archive is a utility for exploring remote archive files without downloading the entire contents of the archive.

[WIP] REMOTE-ARCHIVE Remote-Archive is a utility for exploring remote archive files without downloading the entire contents of the archive. The idea b

null 4 Nov 7, 2022
Mafa is a command-line tool that helps people interact with online websites in a terminal(tty).

Table of Contents A Small Demo Installation Prerequisite Option 1: Cargo install (recommended) Option 2: Build from source Option 3: Prebuilt binaries

Michael Lee 6 Jul 10, 2023
Mafa is a command-line tool that helps people interact with online websites in a terminal(tty).

A Small Demo Installation Prerequisite Option 1: Cargo install (recommended) Option 2: Build from source Option 3: Prebuilt binaries Mafa is for me? W

Michael Lee 6 Jul 23, 2023
Terminal UI for leetcode. Lets you browse questions through different topics. View, solve, run and submit questions from TUI.

Leetcode TUI Use Leetcode in your terminal. Why this TUI: My motivation for creating leetcode-tui stemmed from my preference for tools that are lightw

Akarsh 8 Aug 10, 2023
Rust library to convert RGB 24-bit colors into ANSI 256 (8-bit) color codes with zero dependencies and at compile-time.

rgb2ansi256 rgb2ansi256 is a small Rust library to convert RGB 24-bit colors into ANSI 256 (8-bit) color codes with zero dependencies and const fn. Th

Linda_pp 7 Nov 17, 2022
koyo is a cli tool that lets you run commands as another user. It is similar to doas or sudo.

koyo is a cli tool that lets you run commands as another user. It is similar to doas or sudo.

null 3 Nov 27, 2021
ISG lets you use YouTube as cloud storage for ANY files, not just video

I was working on this instead of my finals, hope you appreciate it. I'll add all relevant executables when I can Infinite-Storage-Glitch AKA ISG (writ

HistidineDwarf 3.6k Feb 23, 2023
⚡️(cd with env) Is a configurable cd wrapper that lets you define your environment per directory.

⚡️cdwe (cd with env) A simple configurable cd wrapper that provides powerful utilities for customizing your envionment per directory. (For ZSH / BASH

teo 20 Aug 6, 2023
An anyrun plugin that lets you search NixOS options.

anyrun-nixos-options An anyrun plugin that lets you search NixOS options. how 2 build? nix build ... or cargo build optionally :) Configuration This p

Michał 4 Aug 24, 2023
Lets you tweak Assassin's Creed Mirage in various ways.

Mirage Tweaks Lets you tweak Assassin's Creed Mirage in various ways. Currently supports adjusting the eject height and sprint speed. Usage Get the la

Assassin's Creed Community 3 Nov 3, 2023
fas stand for Find all stuff and it's a go app that simplify the find command and allow you to easily search everything you nedd

fas fas stands for Find all stuff and it's a rust app that simplify the find command and allow you to easily search everything you need. Note: current

M4jrT0m 1 Dec 24, 2021
A tool that allows you to modify, edit, and recompile the AST script of Artemis engine.

Artemis AST Script Processor This utility offers a set of Rust functions to parse and manipulate Artemis AST-based scripts. Features Tokenization: Con

xmoe 7 Sep 19, 2023
Watch output and trigger on diff!

watchdiff Watch output and trigger on diff! Ever want to have watch output only tell you what changed? And not only what, but when? Now you can! Enter

geno 2 Apr 6, 2022
A ln scraper to read light novels and watch anime in your terminal (Written in rust)

Readme Table of content Why use kami Dependencies Install Linux/mac Windows Honorable mentions Why use kami Well its a fast and easy way to watch anim

mrfluffy 26 Dec 23, 2022
Core lightning (CLN) plugin to watch channel health, gossip health and ping amboss for online status

vitality Core lightning (CLN) plugin to watch channel health, gossip health and ping amboss for online status Installation Building Usage Telegram Opt

null 4 Oct 6, 2023
ddi is a wrapper for dd. It takes all the same arguments, and all it really does is call dd in the background

ddi A safer dd Introduction If you ever used dd, the GNU coreutil that lets you copy data from one file to another, then you may have encountered a ty

Tomás Ralph 80 Sep 8, 2022