간단한 쉘 리디렉션으로 /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()
설정 /dev/ptmx
만으로도 의사 터미널을 얻을 수 있는 것으로 보입니다. 그게 껍질을 만들 것 같아요 -(또는 리디렉션을 수행하는 프로세스)- pty의 마스터 측 소유자입니다.
하지만 슬레이브 측을 어떻게 할당합니까?~할 수 있다슬레이브 측을 할당합니까? 그리고 만약 가능하다면 - 그걸로 무엇을 할 수 있나요? 읽기/쓰기/플러시 타이밍에 영향을 미칠 수 있나요 stty
? 참조할 때 슬레이브 측 프로세스가 내 새 pty에 연결됩니까 /dev/tty
?
답변1
따라서 @muru가 주석에서 지적했듯이 쉘만으로 생성된 pty를 인터페이스하는 간단한 방법은 없는 것 같습니다. 일부만 빼고 다 관리했어요 unlockpt()
. 내가 읽은 것에 따르면여기새로 생성된 pty 잠금을 비활성화하기 위한 몇 가지 컴파일 시간 옵션이 커널에 있을 수 있지만 저는 그렇게 하고 싶지 않았습니다. 그래서 저는 다른 일을 했습니다.
실제로 는 필요하지 않았습니다 grantpt()
. 발견된 설명에 따르면여기/dev/pts/[num]
그것이 하는 일은 장치 파일 의 UID/GID를 변경하는 것뿐입니다 . 그러나 이에 따르면 man mount
이를 처리하는 더 쉬운 방법이 있습니다. 다음은 몇 가지 devpts
마운트 옵션 입니다 .
uid=value
그리고gid=value
- 새로 생성된 PTY의 소유자 또는 그룹을 지정된 값으로 설정합니다. 아무것도 지정하지 않으면 생성 프로세스의 UID 및 GID로 설정됩니다. 예를 들어 다음이 있는 경우 tty 그룹에 GID 5가 있으면
gid=5
새로 생성된 PTY가 그룹에 속하게 됩니다.tty그룹.
- 새로 생성된 PTY의 소유자 또는 그룹을 지정된 값으로 설정합니다. 아무것도 지정하지 않으면 생성 프로세스의 UID 및 GID로 설정됩니다. 예를 들어 다음이 있는 경우 tty 그룹에 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
...커널 문서에서 권장하는 대로 - 이유에 대한 링크를 참조하세요. 또한 my.dll 파일에 몇 줄을 추가하여 위 명령의 효과를 영구적으로 만들었습니다 /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
이는 stdin을 호출하려고 시도하는 작은 C 프로그램을 컴파일하고 unlockpt()
성공하면 새로 생성되고 잠금 해제된 pty의 이름을 인쇄하거나 stdout
자동으로 2를 반환합니다.
이 작업이 완료되면 나만의 것을 만들 수 있습니다.상영다음과 같은 프로세스:
exec 3<>/dev/ptmx
...현재 쉘에서 마스터측 fd를 얻으려면...
(setsid -c "$0" -i 2>&1|tee log) <>"$(./pts <&3)" 3>&- >&0 &
백그라운드에서 의사 터미널의 다른 쪽 끝에서 실행되는 대화형 셸을 가져옵니다. 인쇄된 모든 내용을 >&3
사용자 입력으로 해석합니다 .
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$ hey
$
기본적으로 배경이 있고 기록된 대화형 통역사를 제공합니다.(또는 내가 이것을 실행하고 싶은 다른 것)ala는 screen
많은 오버헤드 없이 내가 선택한 파일 설명자에서 가능합니다.
현재 쉘이 소유한 마스터 측 fd는 슬레이브 측 입력을 제공하는 유일한 수단이며 현재 쉘 프로세스에서만 쓸 수 있습니다.(그리고 그 자식들). 나는 >&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