ttyとかptsとかについて確認してみる

psコマンドのTTY列にttyとかptsはたまた?など表示されますが、良く分かってなかったのでメモ

# 参考

+ [ttyについて ttyやptsってなんぞ？](http://takuya-1st.hatenablog.jp/entry/20101024/1287947368)
+ [ttyとptsの違い](http://d.hatena.ne.jp/alexei-karamazov/20130512/1368321943)
+ [sshで入れなくなっても精神的ダメージを食らわない素敵な方法](http://masudak.hatenablog.jp/entry/20110328/1301316981)

# 調べてみる

ttyについてウィキペディアでは以下のように書いてあります。

>ttyとは、標準入出力となっている端末デバイス(制御端末、controlling terminal)の名前を表示するUnix系のコマンドである。元来ttyとはteletypewriter（テレタイプライター）のことを指す。

これは`tty`コマンドの説明ですね。
ttyコマンドをタイプすることで標準入力、標準出力となっている端末デバイスを表示すると。

試しにターミナルからSSHログインしているサーバーでコマンドを実行してみます。

```bash
# ターミナルAでログイン
$tty
/dev/pts/0
```

上記の`/dev/pts/0`が端末デバイスとなっているようですが、この/dev/pts/0とは何なのでしょうか。

調べてみるとptsはSSHやtelnetで接続している仮想端末（ターミナル)を示すようです。つまり、上記の例ではSSHで接続しているターミナルを標準入力元・標準出力先デバイスとすることでターミナル上に文字の表示をしたり、ターミナルでタイプした入力を受け取るれるようになっているということのようです。

試しに上記SSH接続がされた状態で別のターミナルから同じサーバーにSSHログインしてみます。

```bash
# 別のターミナル(ターミナルB)からSSHログイン
$tty
/dev/pts/1

# ログイン中のユーザーを表示
$w
 08:55:45 up 28 min,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
ec2-user pts/0    h175-177-004-097 08:30    1.00s  0.02s  0.00s w
ec2-user pts/1    h175-177-004-097 08:52    3:32   0.00s  0.00s -bash
```

別のターミナルでは同じユーザーでのSSHログインにも関わらず、`/dev/pts/1`ということで別のファイルがttyに割り当てられていました。別のファイルを割り当てないとターミナルBで標準入力・標準出力を
制御できないからですね。

つまり、現状は以下のような関係となっていることが分かります。

+ ターミナルA->/dev/pts/0
+ ターミナルB->/dev/pts/1

# ファイルディスクリプタとの関係

ファイルディスクリプタとは、プログラムがアクセスするファイルや標準入出力などをOSが識別するために用いる識別子です。

以前ファイルディスクリプタについて記事も書きました。

[ファイルディスクリプタについて理解する](http://qiita.com/toshihirock/items/78286fccf07dbe6df38f)

通常、ファイルディスクリプタは以下のようにそれぞれ割り当てられます。

+ 0->標準入力
+ 1->標準出力
+ 2->標準エラー出力

`/proc/[プロセスID]/fd/`配下を見ることでプロセスごとのファイルディスクリプタの向き先が分かるので確認してみます。

```bash
# ターミナルAで実行
$vim hoge.txt
# Ctrl+Zで停止

# プロセスID確認
$ps
  PID TTY          TIME CMD
 7270 pts/0    00:00:00 bash
 7322 pts/0    00:00:00 vim
 7330 pts/0    00:00:00 ps

# ファイルディスクリプタ確認
$ ll /proc/7322/fd
合計 0
lrwx------ 1 ec2-user ec2-user 64  4月 28 09:14 0 -> /dev/pts/0
lrwx------ 1 ec2-user ec2-user 64  4月 28 09:14 1 -> /dev/pts/0
lrwx------ 1 ec2-user ec2-user 64  4月 28 09:14 2 -> /dev/pts/0
lrwx------ 1 ec2-user ec2-user 64  4月 28 09:14 4 -> /home/ec2-user/.test.txt.swp
```

標準入力、標準出力、標準エラー出力のファイルディスクリプタがそれぞれttyコマンドの結果と同じファイルに向いています。
「/dev/pts/0=ターミナルA」だったので上記起動していたVimはターミナルAから標準入力を受け取り、ターミナルAに標準出力・標準エラー出力を表示しているということが分かりました。

# 遊んでみる

ttyとターミナルの関係が分かり、ttyでは標準出力を受け取れるということなので、/dev/pts/1ファイルを使ってターミナルAからターミナルBにメッセージを送信してみます。

ターミナルAで以下を実行します。

```bash
$echo "hoge" > /dev/pts/1
```

するとターミナルBで標準出力されます。

```bash
$hoge
```

面白いですね。
wコマンドで他のユーザーのttyのファイルを確認し、メッセージの送信ができるということですね。

# psでTTYが「?」となっているのは何？

これは結論から言うとデーモンプロセスです。
デーモンプロセスではユーザーに端末から制御されるものでなく、バックグラウンドで動作するプロセスのためttyが割り当たってないよということを意味するものです。

確認のためデーモンプロセスを書きます。

```deamon.rb
Process.deamon
sleep
```

実行し、確認します。

```bash
# デーモンプロセス起動
$ruby deamon.rb

# プロセス確認
$ps aux |grep deamon
ec2-user 27831  0.0  0.4 135276  4408 ?        Sl   11:38   0:00 ruby deamon.rb
ec2-user 27835  0.0  0.2 110472  2172 pts/1    S+   11:38   0:00 grep --color=auto deamon

# ファイルディスクリプタ確認
$ll /proc/27831/fd/
合計 0
lrwx------ 1 ec2-user ec2-user 64  4月 28 11:40 0 -> /dev/null
lrwx------ 1 ec2-user ec2-user 64  4月 28 11:40 1 -> /dev/null
lrwx------ 1 ec2-user ec2-user 64  4月 28 11:40 2 -> /dev/null
lr-x------ 1 ec2-user ec2-user 64  4月 28 11:40 3 -> pipe:[36988]
l-wx------ 1 ec2-user ec2-user 64  4月 28 11:40 4 -> pipe:[36988]
lr-x------ 1 ec2-user ec2-user 64  4月 28 11:40 5 -> pipe:[36989]
l-wx------ 1 ec2-user ec2-user 64  4月 28 11:40 6 -> pipe:[36989]

```

なるほど。
標準入力、標準出力、標準エラー出力が/dev/nullとなってますね。

Webサーバーのhttpdを確認すると以下のようになってました。

```bash
$sudo ls -la /proc/27933/fd/
合計 0
dr-x------ 2 root root  0  4月 28 11:46 .
dr-xr-xr-x 9 root root  0  4月 28 11:46 ..
lr-x------ 1 root root 64  4月 28 11:46 0 -> /dev/null
l-wx------ 1 root root 64  4月 28 11:46 1 -> /dev/null
l-wx------ 1 root root 64  4月 28 11:46 2 -> /var/log/httpd/error_log
lrwx------ 1 root root 64  4月 28 11:46 3 -> socket:[37368]
lrwx------ 1 root root 64  4月 28 11:46 4 -> socket:[37369]
lr-x------ 1 root root 64  4月 28 11:46 5 -> pipe:[37384]
l-wx------ 1 root root 64  4月 28 11:46 6 -> pipe:[37384]
l-wx------ 1 root root 64  4月 28 11:46 7 -> /var/log/httpd/access_log
```

こちらは標準エラー出力はエラーログに書き込むようになってますね。socketのファイルディスクリプタがあるのでリクエストの際やその他プロセスと通信する場合にはこちらを利用するのだと思われます。

# mingettyってなんだ?

psコマンドを打つとmingettyというプロセスが確認できます。

```bash
$ps aux |grep tty
root      2502  0.0  0.1   6460  1524 ttyS0    Ss+  08:27   0:00 /sbin/agetty ttyS0 9600 vt100-nav
root      2506  0.0  0.1   4312  1384 tty1     Ss+  08:27   0:00 /sbin/mingetty /dev/tty1
root      2509  0.0  0.1   4312  1484 tty2     Ss+  08:27   0:00 /sbin/mingetty /dev/tty2
root      2511  0.0  0.1   4312  1388 tty3     Ss+  08:27   0:00 /sbin/mingetty /dev/tty3
root      2513  0.0  0.1   4312  1488 tty4     Ss+  08:27   0:00 /sbin/mingetty /dev/tty4
root      2515  0.0  0.1   4312  1384 tty5     Ss+  08:27   0:00 /sbin/mingetty /dev/tty5
root      2518  0.0  0.1   4312  1388 tty6     Ss+  08:27   0:00 /sbin/mingetty /dev/tty6
ec2-user 28120  0.0  0.2 110472  2244 pts/3    S+   12:55   0:00 grep --color=auto tty
```

調べてみるとこのmingettyがログインプロンプトを表示することによってユーザーがログインできるようになるもののようです。
ttyだから仮想端末でなく、実際にLinuxマシンにつなぐ際に利用するもののようですね。

以下に書いてあった図が分かり易かったです。

[ttyについて ttyやptsってなんぞ？](http://takuya-1st.hatenablog.jp/entry/20101024/1287947368)

```bash
PC----ssh------/dev/pts/1--sshd----bash #ssh が接続されている
PC----rs232c---/dev/ttyS0--mgetty--bash #rs232c が接続されている
```