CentOS7で作るデジタルサイネージ

この記事は、[Linux Advent Calendar 2016](https://qiita.com/advent-calendar/2016/linux)の記事です。

CentOS 7でデジタルサイネージみたいなものを作ったので、それを記事にします。

デジタルサイネージと言って、下記のイメージを持たれた方はそっと閉じられた方が良いかもしれません。

![](http://img-cdn.jg.jugem.jp/ae0/1827052/20100909_303873.jpg)

実際はこんな感じです。

![Screenshot_2016-12-07_08-40-14.png](https://qiita-image-store.s3.amazonaws.com/0/103885/16a696d3-d0b7-dfe6-082e-1d45c6ee5eb1.png)

「PCを起動すると、あるプロセスの標準出力を出し続ける」環境を構築する手順をご紹介します。

# 動機

この記事では実用性は皆無ですが、これの発展版を社内で使っています。

詳細は伏せますが、「一般社員は何もできない」「でも限られた操作と表示はしたい」
みたいな場合に使えるのではないかと思います。

# 環境

CentOS 7.1 を使います。

CentOS 7系は、Systemdが採用されており、プロセスのデーモン化がかなり簡単になったと思います。

スクリプトを書かずに、設定ファイルを書いていく感じです。

私はupstart時代にデーモン化をしたことが無いゆとりなので、正確な比較はできませんが・・・

# 仕様

デジタルサイネージなので、電源を付けるだけで画面の表示までやってくれるようにします。
ログインやその他の操作を不要にします。

また第三者になるべく操作されたくないので、rootでログインしない限り一切コマンドを実行できないようにします。

# 設計

画面への表示方法としては

- 標準出力をファイルにリダイレクトし、そのファイルを`tail -f`などで出力する方法
- 標準出力をttyコンソールに直接リダイレクトする方法

の2つがありますが、今回は後者の直接リダイレクトを採用します。

なぜなら、ログファイルの削除やログインスクリプトの作成といった工数が減るためです。
（後述しますが、Linuxのログインスクリプトで引数を取ることができません）

もしログファイルを残しておきたいのであれば、前者の方が適切でしょう。

作成するものは下記です。

- ひたすら「Hello World」と出力するだけのプログラム
- 上記をサービス化するための設定ファイル
- 出力を受け取るためのログインユーザー
- 自動ログインするための設定ファイル

なお、今回作成するアプリケーション名は`signage`とします。

# ひたすら「Hello World」と出力するだけのプログラム

```sh:/opt/signage/main.sh
#!/bin/sh
echo 'Hello World'
```

実際のアプリケーションでは、ここが天気予報だったりニュースだったりするでしょう。

# サービス化

上記のスクリプトをサービス化するための設定ファイルを作ります。

```sh:/etc/systemd/system/signage.service
[Unit]
Description = digital signage
After=network.target remote-fs.target nss-lookup.target

[Service]
Type = oneshot
ExecStart = /bin/bash -c '/opt/signage/main.sh  > /dev/tty1'

[Install]
WantedBy = multi-user.target
```

`After=`でネットワークが有効になった後にこのサービスを開始するよう指定しています。
後に天気予報を表示するなどした時に、ネットワークが必要になるためです。

システム同士の関連が分かりやすくて良いですね。

`Type = oneshot` という洋画のような記述は、この場合 `simple` の方が良いかもしれません。


`ExecStart`では、作成したスクリプトを実行し、その出力先を`/dev/tty1`にします。
`/dev/console`も試したのですが駄目でした。

`WantedBy=`では、CentOS6系で言うところのランレベル3以上で起動するようにしています。

このサービスを、自動起動するよう設定します。

```sh
sudo systemctl enable signage.service
```

# ログインユーザーを作成する

次に、自動でログインするためのユーザー`signage`を作成します。

```sh
sudo useradd signage
```

このユーザーには一切の操作をさせたくない、でもログインはできるようにしたいので、
ログインスクリプトに`tail`を指定します。
`tail`にしている理由は無く、`/bin/bash`とかじゃなかったら何でも良いです。

```sh:/etc/passwd
signage:x:1001:1001::/home/signage:/bin/tail
```

試しに`sudo su - signage`などとすると、何もできないでしょう。

ちなみに、このログインスクリプトで引数を取ることはできませんでした。

`/bin/tail /var/log/messages`とか`"bin/tail /var/log/messages"`とかやってみましたが駄目でした。

# 自動ログイン

※この部分は全く自信が無いので、間違っていたら教えてもらえると嬉しいです。

CentOS7では、`getty`というサービスがログインを管理しているみたいです。
`getty@tty1.service`が各`/dev/tty1`へのログインを管理しているようです。

ちなみに、ネットワークを管理しているのは`NetworkManager`というサービスで、
各インターフェースを管理しているのは`NetworkManager@eth0.service`などとなっています。
分かりやすいですね。

で、`getty@tty1.service`の設定をoverrideすることで、自動ログインを可能にします。

```sh:/etc/systemd/system/getty@tty1.service.d/override.conf
[Service]
ExecStart=-/sbin/agetty --autologin signage --noclear %I 38400 linux
```

引数を解説しようと思ったのですが、ここは呪文的に書いてしまったので分かりません・・・すみません。

%Iは、対象のtty(この場合はtty1)が入るらしいです。

# 起動

再起動して、延々と`Hello World`が表示されるのを確認しましょう。お疲れ様でした。

# 参考

- http://enakai00.hatenablog.com/entry/20130917/1379374797
- https://bbs.archlinux.org/viewtopic.php?id=169483
- http://unix.stackexchange.com/questions/150975/what-is-needed-for-a-minimal-systemd-boot-to-launch-getty-on-a-virtual-console
- http://askubuntu.com/questions/659267/how-do-i-override-or-configure-systemd-services