How to trick a command into thinking its output is going to a terminal
A history of toolsets
You are not the first person to want such a tool. People have been wanting such tools for 30 years. And they've existed for almost that long, too.
The earliest tool for this sort of thing was Daniel J. Bernstein's "pty" package, described by Rich Salz as a "Ginsu knife", which Bernstein wrote back at the turn of the 1990s in order to cheat at nethack (sic!). Version 4 of the "pty" package was published in 1992 to comp.sources.unix
(volume 25 issues 127 to 135). It's still locatable on the World Wide Web. Paul Vixie described it at the time:
What can I say? It slices, it dices, it washes dishes, it walks the dog. It "just works", meaning that if you follow the directions you'll get a working package without any pulling of hair or gnashing of teeth or other standard porting activities.
Bernstein later updated this, somewhen on or before 1999-04-07, with a "ptyget" package, which he announced:
I've put together a new pseudo-tty allocator, ptyget. An alpha version is at
ftp://koobera.math.uic.edu/pub/software/ptyget-0.50.tar.gz
. There's a ptyget mailing list; to join, send an empty message to[email protected]
. I designed ptyget's interface from scratch. It's much more modular than pty; the basic pty interface has now been split into three pieces:
ptyget
: a tiny, low-level program — the only setuid program in the package — that allocates a new pseudo-tty and passes it to the program of your choiceptyspawn
: another small program that runs a child process under a pseudo-tty, waiting for it to exit and watching for stopsptyio
: another, only slightly larger, program that moves data back and forthThe old Ginsu knife
pty
is now spelledptybandage
, which is a synonym forptyget ptyio -t ptyspawn
;pty -d
, for attaching network programs to pseudo-ttys, is now spelledptyrun
, which is a synonym forptyget ptyio ptyspawn
; andnobuf
is a synonym forptyget ptyio -r ptyspawn -23x
. I've split off the session management features into a separate package.
That separate package was the "sess" package.
"ptyget" is, incidentally, notable for exemplifying a very early version of, and one of the few published instances of, Berstein's own never-published "redo" build system. dependon
is a clear precursor to redo-ifchange
.
Usage
ptybandage
ptybandage
is what people usually want in a login session. Its primary use case is making programs that are sensitive to whether their standard inputs, outputs, or errors are connected to terminals operate that way even though they are in fact in shell pipelines, or have their standard file descriptors redirected to file.
It takes a command to run (which has to be a proper external command, of course) and runs it in such a way that it thinks that its standard input, output, and error are attached to a terminal, connecting those through to ptybandage
's original standard input, output, and error.
It deals with the nuances of running under job control shells, ensuring that a terminal STOP character not only stops ptybandage
but also stops the program running attached to the inner terminal.
ptyrun
ptyrun
is what people usually want in TCP network servers. Its primary use case is remote execution environments that have not themselves set up terminals, running programs that don't operate as desired when there's no terminal.
It doesn't expect to be running under a job control shell, and if the command being run receives a stop signal it is simply restarted.
Available toolsets
Dru Nelson publishes both "pty" version 4 and "ptyget".
Paul Jarc publishes a fixed version of ptyget, that attempts to deal with the operating-system-specific pseudo-terminal device ioctls in the original that operating systems actually no longer provide.
The nosh source package comes with workalike ptybandange
and ptyrun
scripts, which use Laurent Bercot's execline
tool and the nosh package's own pseudo-terminal management commands. As of nosh version 1.23 these are available pre-packaged in the nosh-terminal-extras package. (Earlier versions only supplied them to people who built from source.)
A few example uses
Jurjgen Oskam using ptybandage
on AIX to feed input from a here document to a program that explicity opens and read its controlling terminal for a password prompt:
$ ptybandage dsmadmc <<EOF >uit.txt joskam password query session query process quit EOF
Andy Bradford using ptyrun
on OpenBSD under daemontools and ucspi-tcp to make the bgplgsh
interactive router control program accessible via the network whilst making it think that it is talking to a terminal:
#!/bin/sh exec 2>&1 exec envuidgid rviews tcpserver -vDRHl0 0 23 ptyrun /usr/bin/bgplgsh
Further reading
- Daniel J. Bernstein (1992-02-19). v25i127: Generalized interface to pseudo-tty devices. comp.sources.unix. 25 (127).
- Daniel J. Bernstein (1991-10-04). An introduction to session management. Bernstein on TTYs. JdeBP.
- Paul Jarc. ptyget. Paul Jarc's software.
- Jonathan de Boyne Pollard (2016). Daniel J. Bernstein's ptyget toolset. Softwares.
- Dru Nelson. drudru/pty4. GitHub.
- Dru Nelson. drudru/ptyget. GitHub.
- Laurent Bercot. execline. software.
- Jonathan de Boyne Pollard (2016). Daniel J. Bernstein's softwares all in one. Softwares.
- Jonathan de Boyne Pollard (2014). The nosh package. Softwares.
- Jonathan de Boyne Pollard (2012). An introduction to
redo
. Frequently Given Answers. - Reyk Floeter.
bgplgsh
. 8. OpenBSD manual pages.
You might get what you need by using unbuffer
.
unbuffer
is a tcl
/ expect
script. Look at the source if you want. Also note the CAVEATS section in man.
Also note that it does not execute aliases such as:
alias ls='ls --color=auto'
unless one add a trick as noted by Stéphane Chazelas:
If you do a alias unbuffer='unbuffer '
(note the trailing space), then aliases will be expanded after unbuffer
.
You can use socat to start your process with a pty connected, and get socat to connect the other end of the pty to a file. Which AFAIU is exactly what you asked:
socat EXEC:"my-command",pty GOPEN:mylog.log
This method will cause isatty
called by my-command
to return true
and a process that relies only on that will be fooled to output control codes. Note that some processes (notably grep
) also check the value of the TERM
environment variable, so you might need to set it to something reasonable, like "xterm"