繁体   English   中英

无法从外部进程读取PTY(伪终端文件)

Can't read PTY (pseudo terminal file) from external process

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在打开PTY(在Python / Linux中)并对其进行写入。 我可以通过minicom完美地阅读它。 但是,我无法在另一个Python(或C ++)程序中读取它。 这是一个最小化的示例:

producer.py(打开pty /对其进行写入):

import os, sys
from time import sleep
master_fd, slave_fd = os.openpty()
print "minicom -D %s" % os.ttyname( slave_fd )
for i in range(0,30): 
    d = str(i % 10)
    os.write( master_fd, d )
    sys.stdout.write( d )
    sys.stdout.flush()
    sleep( 2 )
os.close( slave_fd )
os.close( master_fd )
print "\nDone"    

Consumer.py(尝试打开/读取):

import os, sys
from time import sleep
pts=raw_input("Enter pts number:")
while True:
    fd=0
    try:
        fd=os.open('/dev/pts/%d' % (pts,), 
            os.O_RDONLY | os.O_NONBLOCK )
        sys.stdout.write( os.read(fd, 1 ) )  
        sys.stdout.flush()       
    except Exception as e: print e
    if fd: os.close(fd)    
    sleep(1)        

读取的结果始终是:

[Errno 11]资源暂时不可用

如果我以阻止模式阅读,它只会阻止直到生产者终止。 然后,它说该文件不存在。

我花了数天的时间尝试设置各种模式,权限,锁等,但似乎没有任何事情可以使我无所适从。 这种事情可以很容易地与常规文件配合使用。 另外,请再次注意, minicom可以毫无障碍地读取pty 此外,使用lsof可以看到minicom和我的consumer.py脚本确实打开了文件-在python示例中,仅读取无效。 那么,minicom的秘密是什么? 我尝试在minicom源代码中找到这样的内容,但没有成功找到我可以使用的任何内容。

理想情况下,我的生产者可以很容易地打开和阅读(就像在我的消费者示例中一样),但是如果我能看到这项工作,那么我愿意修改任一端...

2 个回复

是什么让您认为无法打开PTY? 您的代码中没有任何内容提供有关哪个系统调用失败的信息。

最可能的情况是os.read()调用失败,错误代码为EAGAIN (aka EWOULDBLOCK ),因为您已在非阻塞模式下打开了PTY。 因为PTY是tty,所以没有要读取的数据,并且ttys最初处于“煮熟”模式,这意味着在发送行尾字符或某些中断字符之前,不会将任何输入传递给使用者。 Minicom可能会通过termios调用将pty置于“原始”模式,您也应该这样做。

我想您真的不想将PTY置于非阻塞模式。 除非您设置事件轮询或选择循环,否则您将反复获得EAGAIN “错误”(这并不是真正的错误),并且您真的不想等待一秒钟再尝试。 (您也不是真的要关闭并重新打开PTY。)最好将PTY保留为阻塞模式,但将其配置为在每次击键时立即返回(同样,使用termios )。

我的主要挂断是在pty设置中。 看到我的评论@rici的答案。

修改后的producer.py:

import os, sys
from time import sleep
import fcntl
import termios 

# create a new Psdeuo Terminal (pty), with a dynamically 
# assigned path to it, and display the minicom command to 
# open it as a test consumer
master_fd, slave_fd = os.openpty()
print "minicom -D %s" % os.ttyname( slave_fd )

# termios attribute index constants
iflag  = 0
oflag  = 1
cflag  = 2
lflag  = 3
ispeed = 4
ospeed = 5
cc     = 6
# get current pty attributes
termAttr = termios.tcgetattr( master_fd )
# disable canonical and echo modes       
termAttr[lflag] &= ~termios.ICANON & ~termios.ECHO
# disable interrupt, quit, and suspend character processing 
termAttr[cc][termios.VINTR] = '\x00' 
termAttr[cc][termios.VQUIT] = '\x00'
termAttr[cc][termios.VSUSP] = '\x00'
# set revised pty attributes immeaditely
termios.tcsetattr( master_fd, termios.TCSANOW, termAttr )

# enable non-blocking mode on the file descriptor
flags = fcntl.fcntl( master_fd, fcntl.F_GETFL ) 
flags |= os.O_NONBLOCK               
fcntl.fcntl( master_fd, fcntl.F_SETFL, flags )

# write some example data for a couple of minutes
for i in range(0,60): 
    d = str(i % 10)
    os.write( master_fd, d )
    sys.stdout.write( d )
    sys.stdout.flush()
    sleep( 2 )

# release the resources     
os.close( slave_fd )
os.close( master_fd )
print "\nDone"

修改后的consumer.py:

import os, sys
from time import sleep
from errno import EAGAIN, EBUSY

ERRORS_TO_IGNORE = [EAGAIN, EBUSY]

# the PTS will be dynamically assigned to the producer,
# so the consumer needs to have that supplied
pts=raw_input("Enter pts number:")

fd=None
print "Press Ctrl+Z to exit"
while True:
    sleep(1)      
    # if the pty is not open, attempt to open it
    # in readonly, non-blocking mode
    try:
        if not fd:
            fd=os.open('/dev/pts/%s' % (pts,), 
                       os.O_RDONLY | os.O_NONBLOCK )
    except Exception as e:
        print e
        if fd: fd = os.close(fd)     
        continue         
    # attempt to read/pop a character from the stream
    # and then display it in this terminal                 
    try:        
        c = os.read( fd, 1 )
        sys.stdout.write( str(c) )  
        sys.stdout.flush()
    except Exception as e:
        # ignore some "normal" / "race condition" errors
        if( isinstance(e, OSError) and
            e.errno in ERRORS_TO_IGNORE ):pass
        else : print e
1 为什么以及何时在新的伪终端(pty)中启动进程

我正在学习PTY ,我读过神秘的TTY , 什么是“ coproc”? ,并按照此模式测试了一些代码(例如async) , 使父进程派生有新的伪终端(PTY)。 从长远来看,我想了解异步更新提示的方式,我已经看到了一些模式,例如在后台启动父进程( worker & ),使用zpt ...

2019-03-25 17:31:29 0 36   fork/ pty
2 子进程无法从创建的伪终端读取

我正在尝试编写一个可以使用伪终端使用密码登录SSH的应用程序。 但是,如果将write()写入主设备,那么数据就不会出现在从设备中。 这是一个简单的测试用例: 该应用程序将首先输出“按Enter发送字节”。 按Enter后,我希望子进程的read()返回。 但是,即使主服务器的w ...

3 无法从伪终端读取

我编写了一个高级包装器和命令集合,它使用RProc / RPMsg接口与微处理器通信,以便尽可能地测试我为它编写的单元测试使用Linux伪终端来代替'真正的'界面。 我的测试不起作用。 我最终将测试简化到了不包含我的代码痕迹的地步 - 它仍然不起作用: 其输出是: 我可以 ...

4 Netbeans 11终端“无法启动pty进程:”

我在PHP中使用netbeans 64位11。 当我转到终端时,它显示“无法启动pty进程:” 我确定,我安装了Cygwin 64位,并将其添加到Windows路径变量中; C:\\ cygwin64 \\ bin 我想念什么吗? 它曾经在早期版本的netbeans中工作。 谢谢。 ...

5 Net :: SFTP ::外部错误-无法将pty连接为控制终端

这是基于另一个被问到但尚未完全回答的问题。 我遇到了与user2621980相同的行为。 我的错误 当我用truss运行脚本时,它消失了。 另外,请务必注意,当我在Server_A上运行脚本时,它可以正常工作。 但是,当Server_B上的另一个脚本调用(通过ssh调用) ...

8 生成SSH进程(pty.js)并读取本地文件

通过ssh在服务器上运行本地文件非常简单 。 但是,尝试使用spawn的参数数组执行此命令时遇到问题。 例如,从终端可以正常工作: 但是,当尝试使用节点时,它会尝试在远程服务器上查找文件: 导致“没有这样的文件或目录”错误(在远程服务器上查看)。 难道是我在数组中格 ...

9 伪终端(pty)报告资源暂时不可用

我有一个伪终端从属设备,它给我一个资源暂时不可用的读/写错误(11) 。 我一直无法解决这个问题,但直到一个星期前我才知道任何问题。 所以,我可能会遗漏一些明显的东西。 从我所读到的,这可以通过在非阻塞pty上调用read()来引起。 但是,当我open() slave pty后检查 ...

10 自己编写 PTY 伪终端仿真/在 Unix 上用 C 控制交互命令

我的梦想是自己在 Unix 上用 C 编写一个伪终端仿真。 到目前为止我的成就: 我可以与 shell shell 交互并执行非交互命令。 首先,我的程序分叉让子进程执行命令,该命令的输出然后通过管道传输到父进程,父进程将其写入屏幕/STDIN_FILENO。 我的问题:每当我生成任何 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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