我如何让stdin成为一个tty?

时间:2015-02-06 18:32:08

标签: ruby linux unix tty pty

有些程序根据stdout是否为tty来改变输出。因此,如果将这些放在管道中或重定向它们,则输出与在shell中的输出不同。这是一个例子:

$ touch a b c

# when running ls alone, it places them on one line
$ ls
a b c

# when stdout is not a tty, it places them on their own line
$ ls > output

$ cat output
a
b
c
output

所以,如果我想向某人展示这样的命令应该是什么样的(例如我正在编写教程),我必须突出显示并复制终端的输出,然后将其保存到文件中。

似乎我应该能够做到这样的事情:

ls | ttypipe > output

其中ttypipe是一个假设的程序,当被问到是否是tty时,stdin(因此ls的stdout)响应为true。

我知道在Ruby中,我可以这样做:

require 'pty'         # => true
IO.pipe.map(&:tty?)   # => [false, false]
PTY.open.map(&:tty?)  # => [true, true]

但这是针对子进程的,而不是当前进程,因此结果:

$stdin.tty?  # => false

我可以执行,我想不出有办法影响stdin文件描述符。

1 个答案:

答案 0 :(得分:2)

你不能写ttypipe因为管道是管道,而且永远不会是tty。但是,您可以使用稍微不同的语法编写ttyexec

ttyexec ls > output

它将打开一个伪终端,在其中运行ls,并将任何ls个写入终端的ttyexec写入script的标准。

瞧,有一个这样的工具:$ touch a b c $ ls a b c $ script -q -c 'ls' /dev/null > output $ cat output a b c output 。它在一个新的隐藏的pty中打开一个程序来记录与它的交互,但我们可以忽略日志记录部分并只使用它的终端打开属性:

{{1}}