这个选项到底是做什么的?我一直在读TTY,但我仍然感到困惑.我玩的没有-t
和只是-i
,似乎期望用户输入的程序抛出错误没有-t
.为什么启用伪TTY很重要?
当我想连接到我的服务器这样的时候
ssh -a username@my-server.de -p 22
Run Code Online (Sandbox Code Playgroud)
它给了我两个错误消息:
PTY allocation request failed on channel 0
shell request failed on channel 0
Run Code Online (Sandbox Code Playgroud)
当我使用参数时-T
,第一个错误消息消失了.但是如何修复第二个呢?我无法连接.对于其他服务器,我可以毫无问题地连接.
我在MAC OS 10.9上参数-v
显示了这个调试输出:
OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011
debug1: Reading configuration data /etc/ssh_config
debug1: /etc/ssh_config line 20: Applying options for *
debug1: Connecting to xxx.your-server.de [188.40.3.15] port 22.
debug1: Connection established.
debug1: identity file /Users/xxx/.ssh/id_rsa type -1
debug1: identity file /Users/xxx/.ssh/id_rsa-cert type -1
debug1: identity file /Users/xxx/.ssh/id_dsa type -1
debug1: identity file /Users/xxx/.ssh/id_dsa-cert type …
Run Code Online (Sandbox Code Playgroud) 因此,您希望记录进程或子进程的stdout和stderr(单独),如果您没有记录任何内容,则输出与您在终端中看到的不同.
看起来很简单没有?不幸的是,看起来可能无法为这个问题编写一个通用的解决方案,这个解决方案适用于任何给定的流程......
管道重定向是一种分离stdout和stderr的方法,允许您单独记录它们.不幸的是,如果将stdout/err更改为管道,则进程可能会检测到管道不是tty(因为它没有宽度/高度,波特率等)并且可能会相应地更改其行为.为什么改变行为?好吧,一些开发人员利用终端的功能,如果您要写入文件,这些功能没有意义.例如,加载条通常要求将终端光标移回到行的开头,并使用新长度的条覆盖前一个加载条.颜色和字体粗细也可以显示在终端中,但是在平面ASCII文件中它们不能.如果您要将这样的程序的stdout直接写入文件,那么该输出将包含所有终端ANSI转义码,而不是正确格式化的输出.因此,开发人员在向stdout/err写入任何内容之前会执行某种"isatty"检查,因此如果该检查返回false,它可以为文件提供更简单的输出.
这里通常的解决方案是通过使用pty来欺骗这些程序,使管道实际上是ttys - 一个也具有宽度,高度等的双向管道.你将进程的所有输入/输出重定向到这个pty,这就是欺骗进程思考它与真实终端的对话(你可以直接将其记录到文件中).唯一的问题是,通过对stdout和stderr使用单个pty,我们现在无法再区分这两者.
所以你可能想为每个管道尝试不同的pty - 一个用于stdin,一个用于stdout,一个用于stderr.虽然这将在50%的时间内工作,但不幸的是,许多进程会执行额外的重定向检查,以确保stdout和stderr(/ dev/tty000x)的输出路径相同.如果它们不是,则必须有重定向,因此它们会给你相同的行为,就好像你没有pty管道stderr和stdout一样.
您可能认为这种过度检查重定向并不常见,但不幸的是它实际上非常普遍,因为许多程序重用其他代码进行检查,就像在OSX中找到的这些代码一样:
我认为找到解决方案的最佳方式是挑战.如果任何人都可以运行以下脚本(理想情况下通过Python,但此时我将采取任何措施),以便单独记录stdout和stderr,并且你设法欺骗它认为它是通过tty执行的,你解决了问题:)
#!/usr/bin/python
import os
import sys
if sys.stdout.isatty() and sys.stderr.isatty() and os.ttyname(sys.stdout.fileno()) == os.ttyname(sys.stderr.fileno()):
sys.stdout.write("This is a")
sys.stderr.write("real tty :)")
else:
sys.stdout.write("You cant fool me!")
sys.stdout.flush()
sys.stderr.flush()
Run Code Online (Sandbox Code Playgroud)
请注意,解决方案应该适用于任何进程,而不仅仅是此代码.覆盖sys/os模块并使用LD_PRELOAD是击败挑战的非常有趣的方法,但它们并没有解决问题的核心:)
我编写并维护了一个程序rlwrap,它使用伪终端与子进程通信. 在所有Unix(类似)系统中都可以找到伪终端(ptys),但它们在不同平台上的表现略有不同.
例证:在rlwrap
,父进程保持slave pty打开以密切关注子进程的终端设置(在Linux和FreeBSD上可以使用master,例如在Solaris中)
在FreeBSD(8.2)(但不是Linux)上,这会导致孩子的最终输出丢失.例如:
#include <stdio.h>
/* save as test.c and compile with gcc -o test test.c -lutil */
#define BUFSIZE 255
int main(void) {
int master, slave;
char buf[BUFSIZE];
int nread;
openpty(&master, &slave, NULL, NULL, NULL);
if (fork()) { /* parent: */
close(slave); /* leave this out and lose slave's final words ... WHY? */
do {
nread = read(master, buf, BUFSIZE);
write(STDOUT_FILENO, buf, nread); /* echo child's output to stdout */ …
Run Code Online (Sandbox Code Playgroud) 安装 VSCode 后,我开始收到这个特定的通知:
与终端 pty 主机进程的连接无响应,终端可能停止工作。
在我单击重新启动按钮之前,通知不会消失。但是,尽管单击此按钮,但没有发生任何变化,并且几秒钟后再次弹出通知。
这个问题导致我的终端停止工作并且无法运行节点应用程序。
我正在编写一个Python程序,用于在Linux服务器上运行用户上传的任意(因此,在最坏的情况下,不安全,错误和崩溃)代码.抛开安全问题,我的目标是确定代码(可能是任何语言,编译或解释)是否写入了正确的内容stdout
,stderr
以及给定输入的其他文件是否输入到程序中stdin
.在此之后,我需要向用户显示结果.
目前,我的解决办法是使用产卵子进程subprocess.Popen(...)
与文件句柄stdout
,stderr
和stdin
.后面的文件stdin
句柄包含了操作过程中的程序读取输入,并且该程序已终止后,将stdout
和stderr
文件的读取,并检查正确性.
这种方法非常完美,但是当我显示结果时,我无法组合给定的输入和输出,因此输入将出现在与从终端运行程序时相同的位置.即类似的程序
print "Hello."
name = raw_input("Type your name: ")
print "Nice to meet you, %s!" % (name)
Run Code Online (Sandbox Code Playgroud)
stdout
运行后,包含该程序的文件的内容将是:
Hello.
Type your name:
Nice to meet you, Anonymous!
Run Code Online (Sandbox Code Playgroud)
鉴于内容包含该文件stdin
是Anonymous<LF>
.所以,简而言之,对于给定的示例代码(以及,等效地,对于任何其他代码),我想实现如下结果:
Hello.
Type your name: Anonymous
Nice to meet you, Anonymous!
Run Code Online (Sandbox Code Playgroud)
因此,问题是检测程序何时等待输入.
我尝试了以下方法来解决问题:
这允许父进程沿管道单独发送数据,但只能调用一次,因此不适用于具有多个输出和输入的程序 - 正如可以从文档中推断出来的那样.
我在Linux中有一个程序,如果它的stdin/stdout不是TTY(终端设备),它就拒绝运行.是否有一个易于使用的工具,它将创建一个PTY,使用新创建的TTY启动程序,并通过stdin/stdout复制所有数据?
用例不是交互式的,而是脚本的.我正在寻找最轻量级的解决方案,最好不要创建TCP连接,也不需要安装太多其他工具和库.
在ssh上运行命令时,我最近遇到了一些奇怪的行为.我有兴趣听到下面这种行为的任何解释.
正在运行ssh localhost 'touch foobar &'
创建一个名为expect的文件foobar
:
[bob@server ~]$ ssh localhost 'touch foobar &'
[bob@server ~]$ ls foobar
foobar
Run Code Online (Sandbox Code Playgroud)
但是,运行相同的命令但使用-t
强制伪tty分配选项无法创建foobar
:
[bob@server ~]$ ssh -t localhost 'touch foobar &'
Connection to localhost closed.
[bob@server ~]$ echo $?
0
[bob@server ~]$ ls foobar
ls: cannot access foobar: No such file or directory
Run Code Online (Sandbox Code Playgroud)
我目前的理论是,由于触摸过程正在被覆盖,因此伪进程在进程有机会运行之前被分配和未分配.当然,添加一秒睡眠可让触摸按预期运行:
[bob@pidora ~]$ ssh -t localhost 'touch foobar & sleep 1'
Connection to localhost closed.
[bob@pidora ~]$ ls foobar
foobar
Run Code Online (Sandbox Code Playgroud)
如果有人有明确的解释,我会非常有兴趣听到它.谢谢.
我试图在Python中找到一种方法来运行其他程序:
这是我到目前为止所得到的...方法1:
def method1(command):
## subprocess.communicate() will give us the stdout and stderr sepurately,
## but we will have to wait until the end of command execution to print anything.
## This means if the child process hangs, we will never know....
proc=subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable='/bin/bash')
stdout, stderr = proc.communicate() # record both, but no way to print stdout/stderr in real-time
print ' ######### REAL-TIME ######### '
######## Not Possible
print ' ########## RESULTS ########## …
Run Code Online (Sandbox Code Playgroud) 我正在编写一些带有文件的代码,将该文件传递给多个二进制文件之一进行处理,并监视转换过程中的错误.我已经在OSX上编写并测试了以下例程,但linux因为我不清楚的原因而失败了.
#run the command, capture the output so it doesn't display
PTY.spawn(command) {|r,w,pid|
until r.eof? do
##mark
puts r.readline
end
}
Run Code Online (Sandbox Code Playgroud)
运行的命令变化很大,##标记处的代码已简化为本地回显以尝试调试问题.该命令执行,脚本在终端中打印预期的输出,然后抛出异常.
它在Debian系统上产生的错误是: Errno::EIO (Input/output error - /dev/pts/0):
我可以提出的所有命令字符串都会产生错误,当我运行没有本地echo块的代码时,它运行得很好:
PTY.spawn(command) {|r,w,pid|}
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,命令本身执行正常,但似乎debian linux没有发送eof up the pty.PTY文档页面和ruby-doc上的IO似乎没有任何帮助.
有什么建议?谢谢.
-vox-