CentOS Stream 9+PX-Q3U4(px4_drv)+epgrecUNAで録画サーバー構築

# はじめに

- 今年(2022年)前半にRHEL9がリリースされそうなので、CentOSで予行演習した時(2022/2/14)の記録です。
- 本番は想定しておらず、すべての機能が正常に動作するかは試していないのでわかりません。
- 各アプリのバージョンを固定していないので、今後動作に問題が出る可能性があります
- ※※※ 問題があっても自分で対応できる方向けです！自己責任でお願いします！ ※※※

# ざっくり仕様
- CentOS Stream 9
- PLEX PX-Q3U4 + px4_drv
- epgrecUNA 人柱版 (2015/11/14)
- PHP8.0 + php-fpm
- LAMPはリポジトリ版を使用
- MySQLではなくMariaDBを使用
- EPG情報更新はshepherd.phpではなくgetepg.phpを使用
- ブラウザから番組表確認、手動予約、キーワード登録のみ動けばよい

# 必要なファイル
- あらかじめダウンロードして「/usr/local/src」に置いてあるものとします
- px4_drvとrecpt1はgitから取得するため準備不要

|ファイル名 (+配布元リンク)|MD5|備考|
|---|---|---|---|
|[epgrecUNA_151114.tar.gz](https://katauna.hatenablog.com/entry/20151114/1447500516)|7be366e7b0fb765765ea00b5f5ccf351|epgrecUNA本体|
|[epgrecUNA151114Fix1.tar.gz](https://katauna.hatenablog.com/entry/20151205/1449313773)|e0304e724372aa20e729181bd6d174b9|パッチ１|
|[epgrecUNA151114Fix2.tar.gz](https://katauna.hatenablog.com/entry/20160411/1460383655)|d7a96523dfa7237b3e6f49075d92e81c|パッチ２|
|[getepg.tar.gz](https://katauna.hatenablog.com/entries/2015/05/26)|457235b4c4a46af2ca82b60490309e63|EPG更新ツール|
|[epgdumpUNA160127.tar](https://katauna.hatenablog.com/entry/20151114/1447500516)|849bd7aeaba90c8c614a52ad63567c7e|EPG抽出ツール|
|[v3.1.44.tar.gz](https://github.com/smarty-php/smarty/releases)|f15461a51dbfd9209000d38aa4354dd2|新しめのSmarty3.x系|

- ※注：epgrecUNAのダウンロードにパスワードが必要なようですが、当方に聞かれてもお答えできません。

# チューナードライバ (px4_drv)
- 配布元の手順通り変更なし
 - https://github.com/nns779/px4_drv

```
# cd /usr/local/src
# git clone https://github.com/nns779/px4_drv.git
# cd px4_drv
# cd fwtool
# make
# wget http://plex-net.co.jp/plex/pxw3u4/pxw3u4_BDA_ver1x64.zip -O pxw3u4_BDA_ver1x64.zip
# unzip -oj pxw3u4_BDA_ver1x64.zip pxw3u4_BDA_ver1x64/PXW3U4.sys
# ./fwtool PXW3U4.sys it930x-firmware.bin
# sudo mkdir -p /lib/firmware
# sudo cp it930x-firmware.bin /lib/firmware/
# cd ../
# sudo cp -a ./ /usr/src/px4_drv-0.2.1
# sudo dkms add px4_drv/0.2.1
# sudo dkms install px4_drv/0.2.1
# shutdown -r now
# ls /dev/px4video*
/dev/px4video0  /dev/px4video1  /dev/px4video2  /dev/px4video3
```

# 録画コマンド (recpt1)
- 配布元の手順通り変更なし
 - https://github.com/stz2012/recpt1

```
# cd /usr/local/src
# git clone https://github.com/stz2012/recpt1.git
# cd recpt1/recpt1
# ./autogen.sh
# ./configure --enable-b25
# make
# make install
```

# apache httpd
- リポジトリからインストールしてコマンド実行確認と設定ファイルの作成を行います

```
# dnf install httpd
# apachectl -v
・コマンドが実行できることを確認

# vi /etc/httpd/conf.d/epgrec.conf
・編集内容は下記参照

# systemctl start httpd
# systemctl enable httpd
・自動起動を有効にする
```

- epgrec用のエイリアスを設定
 - URLは「http://(サーバーIP)/epgrec」になります

```/etc/httpd/conf.d/epgrec.conf
Alias /epgrec /opt/epgrec
<Directory "/opt/epgrec">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
    SetEnv PHP_VALUE "error_reporting = 725"
</Directory>
```

# PHP
- リポジトリからインストールしてコマンド実行確認と設定ファイルの作成を行います
- 検証時点でのパッケージバージョンは「8.0.13-1.el9」でした

```
# dnf install php php-mbstring php-xml php-gd php-pdo php-mysqlnd php-json php-process php-fpm
※使われないモジュールもありそうなので不要なら減らしてください
※「php-mbstring」「php-mysqlnd」「php-process」あたりがepgrecUNAの動作に必要でしょうか

# php -v
・コマンドが実行できることを確認

# vi /etc/php.ini
※変更箇所のみ抜粋
----------------------------
date.timezone = "Asia/Tokyo"
file_uploads = Off
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = pass
mbstring.encoding_translation = On
mbstring.detect_order = auto
mbstring.substitute_character = none
----------------------------

# systemctl start php-fpm
# systemctl enable php-fpm
・自動起動を有効にする

$ echo "<?php phpinfo(); ?>" > /var/www/html/test.php
・ブラウザから「http://(サーバーIP)/test.php」にアクセスして表示されることを確認

$ rm /var/www/html/test.php
```

# データベース(mariadb)
- リポジトリからインストールしてコマンド実行確認と設定ファイルの作成を行います

```
# dnf install mariadb mariadb-server
# mysql -v
・コマンドが実行できることを確認

# systemctl start mariadb
# systemctl enable mariadb
・自動起動を有効にする

# cd /etc/my.cnf.d
# vi mariadb-server.cnf
----------------------------
[mysqld]
character-set-server = utf8
----------------------------

・初期データベースを削除してmysql_secure_installationを実行しておく
　（※このあたりのお作法は人によりますので省いても構わないです）
# systemctl stop mariadb
# mv /var/lib/mysql /var/lib/mysql.old
# mysql_install_db
# chown mysql. -R /var/lib/mysql
# systemctl start mariadb
# mysql_secure_installation
```

- epgrec用のユーザーとデータベースを作成する
 - 「password」は変更すること

```
# mysql -p -u root
----------------------------
MariaDB [(none)]> CREATE USER epgrec@localhost IDENTIFIED BY 'password';
MariaDB [(none)]> CREATE DATABASE epgrec CHARACTER SET UTF8;
MariaDB [(none)]> GRANT ALL ON epgrec.* TO epgrec@localhost;
MariaDB [(none)]> quit
----------------------------

# mysql -p -u epgrec epgrec
・設定したパスワードで接続できることを確認
・Ctl+Dで終了
```

# epgdump
- 展開して make & make install する

```
# cd /usr/local/src
# tar xvf epgdumpUNA160127.tar
# cd epgdumpUNA160127
# make
# make install
```

# epgrecUNA
- 展開してパッチを当てていく

```
# cd /usr/local/src
# tar zxvf epgrecUNA_151114.tar.gz
# tar zxvf epgrecUNA151114Fix1.tar.gz
# tar zxvf epgrecUNA151114Fix2.tar.gz

# #wget https://github.com/smarty-php/smarty/archive/refs/tags/v3.1.44.tar.gz
# tar zxvf v3.1.44.tar.gz
# mv epgrec/Smarty epgrec/Smarty.old
# mv smarty-3.1.44/libs epgrec/Smarty

# chown apache. -R epgrec
# mv epgrec /opt/
# cd /opt/epgrec
# chmod 777 templates_c video thumbs settings cache
# cp -p config.php config.php.init
# vi config.php
・必要な設定を行ってください
```

- PX-Q3U4でのconfigのdiffを張っておきます。録画機器で変わるのであくまで参考用です。
- ユーザーとグループは「apache」にします。

```
# diff config.php.init config.php
　　　　：
チューナー設定は省略
　　　　：
75c75
< define( 'TUNER_UNIT1', 0 );							// 各放送波の論理チューナ数(地上波･衛星波で共用 ex.PT1が1枚なら2)
---
> define( 'TUNER_UNIT1', 4 );							// 各放送波の論理チューナ数(地上波･衛星波で共用 ex.PT1が1枚なら2)
131c131
< 			'device'   => '',				// デバイス指定する場合にコマンドのオプションも含めて記述
---
> 			'device'   => '/dev/px4video2',			// デバイス指定する場合にコマンドのオプションも含めて記述
135c135,143
< 			'device'   => '',
---
> 			'device'   => '/dev/px4video3',
> 		),
> 		2 => array(
> 			'reccmd'   => 0,				// 録画コマンド指定 $rec_cmds中からどれを使うか選択
> 			'device'   => '/dev/px4video6',			// デバイス指定する場合にコマンドのオプションも含めて記述
> 		),
> 		3 => array(
> 			'reccmd'   => 0,
> 			'device'   => '/dev/px4video7',
142c150
< 			'device'   => '',
---
> 			'device'   => '/dev/px4video0',
146c154,162
< 			'device'   => '',
---
> 			'device'   => '/dev/px4video1',
> 		),
> 		2 => array(
> 			'reccmd'   => 0,
> 			'device'   => '/dev/px4video4',
> 		),
> 		3 => array(
> 			'reccmd'   => 0,
> 			'device'   => '/dev/px4video5',
202,203c218,219
< define( 'HTTPD_USER', 'www-data' );					// HTTPD(apache)アカウント
< define( 'HTTPD_GROUP', 'www-data' );					// HTTPD(apache)アカウント
---
> define( 'HTTPD_USER', 'apache' );					// HTTPD(apache)アカウント
> define( 'HTTPD_GROUP', 'apache' );					// HTTPD(apache)アカウント
```

- そのままではPHP8で動作しないので書き換えます
- 差分箇所のみ抜粋「static」を追加する

```DBRecord.class.php
< function sql_escape( $str ){
> function static sql_escape( $str ){
```

```Keyword.class.php
< private function setWeekofdays( $weekofday = 0x7f ){
> private static function setWeekofdays( $weekofday = 0x7f ){
```

- キーワード予約でSQLのUPDATEクエリが失敗する対策
 - integerのカラムに空文字列を入れてupdateされているため、UIがチェックボックスになっているところを確実に0か1に置き換えておく
 - 差分箇所のみ抜粋「? 1 : 0」を追加する

```programTable.php
$smarty->assign( 'kw_enable', $kw_enable ? 1 : 0 );
$smarty->assign( 'overlap', $overlap ? 1 : 0 );
$smarty->assign( 'k_typeGR', $typeGR ? 1 : 0 );
$smarty->assign( 'k_typeBS', $typeBS ? 1 : 0 );
$smarty->assign( 'k_typeCS', $typeCS ? 1 : 0 );
$smarty->assign( 'k_typeEX', $typeEX ? 1 : 0 );

$smarty->assign( 'use_regexp', $use_regexp ? 1 : 0 );
$smarty->assign( 'ena_title', $ena_title ? 1 : 0 );
$smarty->assign( 'ena_desc', $ena_desc ? 1 : 0 );
$smarty->assign( 'collate_ci', $collate_ci ? 1 : 0 );

$smarty->assign( 'discontinuity', $discontinuity ? 1 : 0 );

$smarty->assign( 'criterion_enab', $criterion_enab ? 1 : 0 );
$smarty->assign( 'rest_alert', $rest_alert ? 1 : 0 );
$smarty->assign( 'smart_repeat', $smart_repeat ? 1 : 0 );
```

- 適当なIDでshmop_openすると失敗するようなのでftokを使用するように戻す
 - 元のコメントアウトを外して末尾のreturnをコメントアウト
 - ftokの第二引数は文字に変換しないとエラーになるのでchr()を追加

```reclib.php
function get_ipckey( $id ){

        if( !file_exists( FTOK_KEY ) ){
                $handle = fopen( FTOK_KEY, 'w' );
                fwrite( $handle, 'a' );
                fclose( $handle );
//              exec( 'sync' );
        }
        return ftok( FTOK_KEY, chr($id) );      // ftok()は、仕様上で唯一性を担保できないバグあり

//      return $id;
}
```

- ブラウザから「http://(サーバーIP)/epgrec」にアクセスして画面に従い初期設定を行う

# getepg.php導入
- shepherd.phpが動かなかったのでgetepg.phpを導入します

```
# cd /opt/epgrec
# tar zxvf /usr/local/src/getepg.tar.gz
# cp do-record.sh.sample do-record.sh
# chmod +x do-record.sh
# chown apache. do-record.sh
# crontab -e
----------------------------
# update epg
30 5 * * * sudo -u epgrec /opt/epgrec/getepg.php >/dev/null 2>&1
----------------------------
```
- 毎朝5:30になっていますが適当に変更してください

# apacheユーザーからのat操作を許可する
- apacheユーザーではatを実行できない(コマンドは実行されるが登録されない)ようなので別のユーザー「epgrec」で実行できるようにする

```
# useradd -M -s /bin/bash epgrec
# echo "apache ALL=(epgrec) NOPASSWD: /bin/at" > /etc/sudoers.d/epgrec_at
```

- 「使用コマンドのパス設定」にスペースを含められないので間に挟むスクリプトを作成します。

```
# vi /opt/epgrec/at.sh
・編集内容は下記参照

# vi /opt/epgrec/atrm.sh
・編集内容は下記参照

# chown apache. /etc/epgrec/at.sh /etc/epgrec/atrm.sh
# chown +x /etc/epgrec/at.sh /etc/epgrec/atrm.sh
```

```/opt/epgrec/at.sh
#!/bin/bash
sudo -u epgrec /bin/at $*
```

```/opt/epgrec/atrm.sh
#!/bin/bash
sudo -u epgrec /bin/atrm $*
```

- ブラウザから「使用コマンドのパス設定」画面でatコマンドを以下に変更
> /opt/epgrec/at.sh

- ブラウザから「使用コマンドのパス設定」画面でatrmコマンドを以下に変更
> /opt/epgrec/atrm.sh

```
1) ブラウザから適当に手動予約を実行する
# atq
・予約を実行するスクリプトがキューに登録されていることを確認

2) ブラウザから予約を削除する
# atq
・キューから削除されたことを確認
```

# おまけ
- 稼働状況をモニターする

```
# watch -n 1 "atq | sort | head -8; echo; ls -l /tmp 2>/dev/null | grep "tuner_"; echo; ps -ef | grep recpt1 | grep -v grep"
```

- ブラウザからの操作でうまく動かないときはこのあたりのログを参照

```
# tail -f /var/log/php-fpm/* /var/log/httpd/* /var/log/mariadb/*
```

- ログを見ながらブラウザで操作してみる
 - エラーが出ていたらPHPスクリプトの該当箇所を読んでみるか、コマンドラインから直接スクリプトを実行してみるなどして原因を追跡

 - デバッグのためにログが必要な場合は「/etc/httpd/conf.d/epgrec.conf」にあるerror_reportingの値を変更するか行ごとコメントしてください
 - デフォルトではログに大量のWARNINGが出力されるため、普段はログレベルを変更しておくことをお勧めします

- SQLエラーが出た場合
 - 「mysql -p -u epgrec」で問題のあるクエリを直接実行(コピペ)して挙動を確認する

- ここまでやって、epelにもepel-nextにもffmpegが無いことに気づきました。

- あとは自分で頑張りましょう

# さいごに
- 各ソフトを開発・公開してくださっている方々に感謝致します