Friday, May 28, 2010

虚假终端: pseudo-terminal

之前只听前pseudo terminal, 但是没有理会. 前段时间在写脚本时受点一点限制 

1. 为什么使用subprocess无法与子进程多次通信?
2. 像su这种为什么使用subprocess无法调用? ( 这种软件有一个词来描述: hard wire , 表示需要terminal, 代码中使用了istty函数检测到 )
3. vim这种软件的交互是怎么实现的?

subprocess的communicate函数是代码是这样的:

            if self.stdin:
                if input:
                    self.stdin.write(input)
                self.stdin.close()

这里为什么需要self.stdin.close()呢? 这就是subprocess无法与子进程多次通信的地方.
在不明白为什么需要close的情况下, 自己写的一段fork功能的代码, 結果: 当父进程在读子进程的stdout时被block了. 其实, 这时父进程和子进程都是block的, 这被称为"死锁". 这就是为什么subprocess里需要close

那么, 我的需求:
1. 在调用外部进程的情况下, 如何多次父-子进程通信?
2. 如何调用hard wire的程序?

种种问题的浮现让sysadmin岗位的本人不爽. 至少不方便工作....

例子:
1. passwd的调用
passwd是一典型的hard wire程序, 下面的方式调用是不行的:
$ echo "new password" | passwd
比较有意思的是passwd在不同的系统或者是distro下都是不同的.
 * freeBSD下有参数控制(具体的忘了, 也没有环境回顾), 成为batch mode
 * redhat系使用"--stdin"控制
 * ubuntu下没有batch mode参数

2. su -c "my command"的调用
使用在系统上使用su ( 我不得不说, 没有sudo使用~~~), 这将是一个很大的麻烦~~

后知后觉, 发现了pseudo terminal这一概念. 它的应用很广泛, 比如提供network login的sshd就使用到此概念


在朋友(mrluanma (AT) gmail.com)的帮忙下, 找到pexpect程序(http://www.noah.org/wiki/Pexpect). 提供了一个很好的学习模板.

刚接触pseudo terminal很头大的, 还好APUE一书中有这部分和关于terminal I/O的资料, 下面是一个很清晰的图:


本人写了两个简单的例子:
1. 使用pty.fork()函数产生子进程, 子进程与父进程的controlling terminal是不同的.
帐号与密码都是svn

2. 使用pty实现调用passwd这种hard wire外部程序
帐号与密码都是svn





No comments:

Post a Comment

Note: Only a member of this blog may post a comment.