Skip to content
js4000allPublic

About

XorgでLinuxでウィンドウを表示してみる

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

簡易デジタルサイネージ

Getting Started

ユーザをdev_userとする。

your_homeの内容をホームディレクトリ直下に置く。

/home/dev_user
  - scripts/
  - .bash_profile
  - .xinitrc

tty1を自動ログインにする。systemdのgettyにoverrideを作る。

sudo systemctl edit getty@tty1.service

開いたエディタで、以下を入れる。

[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin dev_user --noclear %I $TERM
  1. PC起動
  2. gettyのExecStartに指定したコマンドが実行され、dev_userで自動ログイン
  3. ログインに伴って~dev_user/.bash_profileが実行される。tty1の場合のみxstartが呼ばれるように書いてある。
  4. XOrgのプロセスで~/.xinittrが実行される。~/scripts/xxx.js(playwrightコード)が呼ばれるようにしてある。
  5. playwrightによりChromiumを起動し、所定の操作を経て所定のページを開く

Xorgを試す

Node.js, Playwright, Chromiumを試す

sudo apt update
sudo apt install -y nodejs npm
node --version
npm --version

cd ~/exam
npm init -y
npm install playwright

npx playwright install --with-deps chromium

単純にChromiumを実行してみる。

# exam内で
node 00_launch.js

スクショを取ってみる。

# exam内で
node 01_screenshot.js
ls -lh example.png

Xorgを試す

sudo apt update
sudo apt install -y xserver-xorg xinit x11-xserver-utils

.inittrcを作る。

cat > ~/.xinitrc <<'EOF'
#!/bin/sh

xset s off
xset -dpms
xset s noblank

exec sleep infinity
EOF

chmod +x ~/.xinitrc

コンソールで、

startx

真っ黒な画面が出る。

sshなどで、Xセッションが存在しているのを確認。

$ ps aux | grep Xorg
user        16294  1.1  2.3 545028 92488 tty1     Sl   22:26   0:00 /usr/lib/xorg/Xorg -nolisten tcp :0 vt1 -keeptty -auth /tmp/serverauth.Rb7zplTzgV
user        16395  0.0  0.0   6520  2348 pts/4    S+   22:27   0:00 grep Xorg

X displayをターゲットに、playwrightでchromiumを起動する。

# exam内で
DISPLAY=:0 node 02_headed.js

kioskオプション付きでも表示してみる。

# exam内で
DISPLAY=:0 node 03_kiosk.js

これは上手く行かない。キオスクモードにならない。

app=で表示してみる。

# exam内で
DISPLAY=:0 node 04_app.js

これは期待通りになった。

  • --kioskはchromiumに渡っているが、キオスクモードにならなかった
  • --app=URL + --window-position + --window-sizeなら、WMなしでも期待どおりの表示になった

外部モニタを使ってみる

$ DISPLAY=:0 xrandr
LVDS-1 connected primary 1280x800+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
   1280x800      59.91*+
   ...
VGA-1 connected
   1024x600      59.98 +
   1920x1080     60.00
   ...

外部モニタだけを有効化する。

DISPLAY=:0 xrandr \
  --output LVDS-1 --off \
  --output VGA-1 --mode 1024x600 --primary
$ DISPLAY=:0 xrandr
Screen 0: minimum 320 x 200, current 1024 x 600, maximum 8192 x 8192
LVDS-1 connected (normal left inverted right x axis y axis)
  1280x800      59.91 +  59.81
  ...
VGA-1 connected primary 1024x600+0+0 (normal left inverted right x axis y axis) 510mm x 290mm
  1024x600      59.98*+
  ...

xrandrの"connected primary"の部分を拾って、動的にwindow sizeを設定するバージョン。

# exam内で
DISPLAY=:0 node 05_flexible_window.js

メインモニターを切り替えて、追従するか試す。

DISPLAY=:0 xrandr   --output LVDS-1 --mode 1280x800  --primary   --output VGA-1 --mode 1024x600

コンソールはそのままで外部モニタにchromiumを出力

3つのグループ

仮想ターミナル

tty1, tty6などは Linux の仮想ターミナルの番号。物理キーボードと画面を使うCUIセッションの「席番号」のようなもの。

vt6のvtは Virtual Terminal の略で、実質的に同じ。Xorgを

Xサーバのdisplay識別番号

:0はX11のdisplay番号。Xサーバの識別番号。

Xorg :0 vt6

なら、:0というX displayは6番の仮想ターミナルを使うという意味。

DISPLAY=:0 chromium

とすると、「X display 0番に接続して、chromiumを表示」という意味。

モニター

実際のモニターは別の番号体系で、xrandr の出力。

LVDS-1
VGA-1
HDMI-1

まとめると、全体像はこう。

VT / tty(仮想ターミナル)
  ↓
Xorg display(Xサーバのdisplay識別番号)
  ↓
xrandr output(実際のモニター)
① Linux VT
   tty1 / vt1
   tty6 / vt6
        │
        │ どの表示環境がGPUを使うか
        ▼
② Xサーバー
   :0
   :1
        │
        │ Xorgが管理する物理出力
        ▼
③ Connector / Output
   LVDS-1
   VGA-1
   HDMI-1
        │
        ▼
   物理モニター

2つの仮想ターミナルを同時利用できるかの実験

今回は関係性を確認したいので、前回と同じ vt1 上でそのまま startx するのではなく、Xorgを別VTに載せる形で試す。

現状はこう。

$ systemctl list-units 'getty@tty*.service'
  UNIT               LOAD   ACTIVE SUB     DESCRIPTION
  getty@tty1.service loaded active running Getty on tty1
  getty@tty6.service loaded active running Getty on tty6

SSH側から tty6 の getty を止めて、空ける。

sudo systemctl stop getty@tty6.service

この時点で以下のようになる。内蔵パネルには変化無し。

$ systemctl list-units 'getty@tty*.service'
  UNIT               LOAD   ACTIVE SUB     DESCRIPTION
  getty@tty1.service loaded active running Getty on tty1

実験としては、まずroot権限でXorgをVT6に直接起動して、VT6でXが動くかだけ確認。 実機上で、

sudo Xorg :0 vt6 -nolisten tcp

起動した。vt1=CUI, vt6=xorgという状態になった。

$ DISPLAY=:0 xrandr --output LVDS-1 --off --output VGA-1 --mode 1024x600 --primary
$ DISPLAY=:0 xrandr
Screen 0: minimum 320 x 200, current 1024 x 600, maximum 8192 x 8192
LVDS-1 connected primary (normal left inverted right x axis y axis)
    1280x800      59.91 +  59.81
    ...
VGA-1 connected 1024x600+0+0 (normal left inverted right x axis y axis) 510mm x 290mm
    1024x600      59.98*+
    ...

出力先の変更もできた。物理世界では、xorgがVGAにだけ表示され、内蔵パネルがオフな状態になっている。

ここでPCを再起動したところ、上記の手順が再現しなくなった。

Playwrightを自動起動する

  • getty(tty1)に仕込みを入れ、起動時に自動ログインするようにする
  • 対象ユーザの.bash_profileでstartxする
  • .xinitrcを編集し、Xサーバ起動時にPlaywrightラッパーを実行するようにする
電源ON
  ↓
Debian起動
  ↓
tty1へ自動ログイン (getty@tty1.service)
  ↓
.bash_profile
  ↓
startx
  ↓
.xinitrc
  ├─ xset
  ├─ xrandr
  └─ Node / Playwright
        ↓
      Chromium --app=...

Xサーバ起動時にPlaywrightが起動するようにする

まず、.xinitrcをサイネージ起動スクリプトに変える。

cat > ~/.xinitrc <<'EOF'
#!/bin/sh

# 画面ブランキングを無効化
xset s off
xset -dpms
xset s noblank

# 外部モニターを使用する場合
# 現在の試験機では VGA-1。最終的には現場PCに合わせる。
xrandr \
  --output LVDS-1 --off \
  --output VGA-1 --auto --primary

# Playwrightラッパーを起動
cd ~/try-xorg/exam
exec node 05_flexible_window.js
EOF

chmod +x ~/.xinitrc

ここではDISPLAY=:0は不要。 .xinitrcはstartxが起動したXセッション内で実行するので、DISPLAYはすでに設定されているため。

exec nodeにより、シェルがnodeプロセスに置き換わることで、chromiumを閉じるとXサーバも終了する挙動になる。

起動時に自動ログインする

次にtty1を自動ログインにする。systemdのgettyにoverrideを作る。

sudo systemctl edit getty@tty1.service

開いたエディタで、以下を入れる。

[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin user --noclear %I $TERM

--autologin userの部分は対象ユーザ名にする。

sudo systemctl daemon-reload

ログインした時にstartxを実行する

さらに、ログインしたtty1で自動的にstartxする。 Bashなら~/.bash_profileに以下を追加。

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

if [ "$(tty)" = "/dev/tty1" ] && [ -z "$DISPLAY" ]; then
    exec startx
fi

tty1以外では通常起動にするのがミソ。

今後の課題

SHOULD

  • 外部モニター未接続時の挙動を決める

    • 内蔵パネルへフォールバックする
    • 外部モニターが接続されるまで待機する
    • 一定間隔で再検出する
  • xrandr の失敗時処理を追加する

    • 対象出力が存在しない
    • 指定解像度が利用できない
    • 外部モニターが途中で切断された
  • Playwright側のログを整備する

    • 起動
    • Chromium起動
    • ページ遷移
    • 表示切り替え
    • 例外
    • Chromium終了
  • ネットワーク・Webサイト障害時の復旧方法を決める

    • DNS失敗
    • 接続タイムアウト
    • HTTPエラー
    • page.goto() 失敗
    • 回復不能時はプロセスを終了し、既存の自動再起動経路に任せる
  • 認証情報をソースコードから分離する

    • GitへID・パスワードを含めない
    • 専用設定ファイルや環境変数などから読み込む
    • ファイルを使用する場合はアクセス権を制限する
  • 実機でVT切り替えによる保守操作を確認する

    • Ctrl + Alt + F2 などでCUIへ移動できること
    • 作業後にXorg側のVTへ戻れること
    • サイネージ表示が正常に復帰すること

MAY

  • 外部モニターの自動検出を実装する

    • VGA-1 / HDMI-1 などの出力名に依存しない
    • 内蔵パネル以外の connected output を自動選択する
    • 現在有効なoutputの解像度をChromiumのwindow sizeへ反映する
  • 外部モニターのホットプラグに対応する

    • 起動後の接続を検出する
    • 切断後の再接続を検出する
  • 縦置きサイネージに対応する

    • xrandr による画面回転
    • 回転後のwindow size調整
  • マウスカーソルを非表示にする

  • NTPによる時刻同期を確認する

  • Playwright / Chromiumのバージョンを固定する

    • 動作確認済みの組み合わせを維持する
    • 更新時にはサイネージ動作を再確認する
  • Chromium起動オプションを設定ファイルへ切り出す

  • 表示対象URLやselect切り替え間隔を設定ファイルへ切り出す

  • systemdサービス化を検討する

    • Restart制御
    • journalへのログ集約
    • 起動依存関係の明示
    • 現状の getty -> autologin -> startx -> .xinitrc 構成と比較してメリットがある場合のみ採用する

About

XorgでLinuxでウィンドウを表示してみる

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages