似乎一个简单的 shell 重定向就为/dev/ptmx
我提供了一个新的伪终端。
$ ls /dev/pts; ls /dev/pts </dev/ptmx
0 1 2 ptmx
0 1 2 3 ptmx
一旦拥有 fd 声明的进程/dev/ptmx
退出,它就会消失,但保留它很简单:
$ PS1='<$(ls -1 "$@" /dev/pts/*|uniq -u)> $ ' \
exec 3<>/dev/ptmx "$0" -si -- /dev/pts/*
</dev/pts/3> $ ls /dev/pts; exec 3>&-
0 1 2 3 ptmx
<> $ ls /dev/pts; exec 3<>/dev/ptmx
0 1 2 ptmx
</dev/pts/3> $ exit
所以看起来简单的open()
on/dev/ptmx
就足以获得一个伪终端。我想这会让外壳 -(或其执行重定向的进程)- 公司主方的所有者。
但是我如何分配从属端 - 或者能我分配从属端?如果可以的话——我能用它做什么?我可以用 影响它的读/写/刷新时间吗stty
?在引用时,从属端进程会链接到我的新 pty/dev/tty
吗?
答案1
因此,正如 @muru 在评论中指出的那样,似乎没有一种简单的方法可以仅使用 shell 来连接为您创建的 pty。除了部分之外,我全部都做到了unlockpt()
。根据我读到的东西这里内核中可能有一些编译时选项用于禁用新创建的 pty 锁定,但我不想这样做。所以,我做了别的事情。
我其实不需要grantpt()
。根据描述发现这里它所做的只是更改设备文件的 UID/GID /dev/pts/[num]
。但据报道,man mount
有更简单的方法来处理这个问题。以下是一些devpts
安装选项:
uid=value
和gid=value
- 这会将新创建的 PTY 的所有者或组设置为指定的值。当没有指定任何内容时,它们将被设置为创建进程的UID和GID。例如,如果有一个 终端 GID 5 的组,
gid=5
则将导致新创建的 PTY 属于终端团体。
- 这会将新创建的 PTY 的所有者或组设置为指定的值。当没有指定任何内容时,它们将被设置为创建进程的UID和GID。例如,如果有一个 终端 GID 5 的组,
默认情况下,我的系统就已经是这种情况了。但读完之后,我意识到我最终可能想做出改变。下一节写道:
ptmxmode=value
- 设置文件系统中新 ptmx 设备节点的模式
devpts
。 - 由于支持多个实例
devpts
(请参阅上面的选项),每个实例在文件系统newinstance
的根目录中都有一个私有 ptmx 节点devpts
(通常/dev/pts/ptmx
)。 - 为了兼容旧版本的内核,新的 ptmx 节点的默认模式是
0000
.ptmxmode=value
为 ptmx 节点指定更有用的模式,并且在newinstance
指定该选项时强烈建议使用。
- 设置文件系统中新 ptmx 设备节点的模式
虽然不这样做也可以工作,但我喜欢这个想法并将其设置0640
为内核文档。顺便说一句,内核文档链接详细介绍了newinstance
挂载选项 - 这非常酷,基本上使您能够在每次挂载时获得一组单独的名称空间 pty /dev/ptmx
。
无论如何,所以别的东西大部分为:
mount -o remount,newinstance,gid=5,ptmxmode=0640 /dev/pts
mount --bind /dev/pts/ptmx /dev/ptmx
...正如内核文档建议的那样 - 请参阅有关原因的链接。我还通过向我的/etc/fstab
.
和...
<<\C cc -xc - -o pts
#include <stdio.h>
int main(int argc, char *argv[]) {
if(unlockpt(0)) return 2;
char *ptsname(int fd);
printf("%s\n",ptsname(0));
return argc - 1;
}
C
它只是编译一个微小的 C 程序,尝试调用unlockpt()
其 stdin,如果成功,则将新创建和解锁的 pty 的名称打印到,否则stdout
默默返回 2。
一旦完成,我就可以创建自己的筛选的流程如下:
exec 3<>/dev/ptmx
...在当前 shell 中获取主端 fd 然后...
(setsid -c "$0" -i 2>&1|tee log) <>"$(./pts <&3)" 3>&- >&0 &
这会在后台伪终端的另一端运行一个交互式 shell。它将把打印的任何内容解释>&3
为用户输入。
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$ hey
$
这基本上为我提供了一个后台、日志、交互式解释器(或者我可能想在这些上运行的其他任何东西)alascreen
没有那么多开销,并且在我选择的任何文件描述符上。
我当前 shell 拥有的主端 fd 是服务从端输入的唯一方法,并且只能由我当前 shell 进程写入(及其子项)。我可以通过写入与另一端进行通信>&3
,并且可以根据需要从同一文件或日志文件中读取。
毕竟stty
在终端上确实有效:
mikeserv@localhost$ echo stty -a ">$(tty)" >&3
speed 38400 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc
-ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl
echoke