単純なシェルリダイレクトが/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
。私の考えでは、これは殻を作ると思います -(またはリダイレクトを実行するプロセス)- 本会社のオーナーです。
しかし、スレーブ側をどのように割り当てますか?できるスレーブ側を割り当てますか?それでは - それで何ができますか?読み取り/書き込み/更新時間に影響を与える可能性がありますかstty
?参照すると、スレーブ側のプロセスは私の新しいptyに接続されますか/dev/tty
?
答え1
したがって、@muruがコメントで指摘したように、シェルだけを使用して生成された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
...現在のシェルからデフォルトの側面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