ホーム » コンピュータ » Linux » Debian (ページ 2)

Debian」カテゴリーアーカイブ

システム

最近の投稿

アーカイブ

カテゴリー

nodejs の更新方法の”更新”と hb-service

自宅で動かしている HomeBridge 、定期的に node-js の更新のために、”hb-service update-node” を実行しているけど、途中に警告メッセージがでるようになった。どうも https://deb.nodesource.com/setup_X での更新は非推奨で https://deb.nodesource.com/node_XX.x での更新に変更となったらしい。単純に警告で表示された URL にアクセスし、新しいインストール方法に従って、下記を実行する。

$ sudo apt-get update
$ sudo apt-get install -y ca-certificates curl gnupg
$ sudo mkdir -p /etc/apt/keyrings
$ sudo curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
$ NODE_MAJOR=18
$ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
  | sudo tee /etc/apt/sources.list.d/nodesource.list
$ sudo apt-get update
$ sudo apt-get install nodejs -y

自作スクリプトのエラー対策 try-catch

自宅で動かしているスクリプト、自前だから手抜きもあって、サーバトラブル時には他の機器が巻き込まれてエラーが増えることも多い。自室の homebridge などを動かしている Raspberry-Pi が暑さもあってか、再起動させたら一時的に気絶。復旧は問題なかったけど、気絶中に他の外気温測定のRaspberry-Pi がブローカーとなっている Raspberry-Pi が落ちているため、MQTT のデータ送信に失敗のエラーを出してる。

ちゃんと、connect で出るエラーを try-except で例外処理を追加した。

try :
  client = mqtt.Client( ... )
  client.connect( BROKER )

  client.publish( ... )
except ValueError as err :
  print( err )
except OSError as err :
  print( err )

以前から、トラブル時にウザいのが、Perl で書かれた RSS 情報をまとめるスクリプト。Perl での try-catch もどきということで eval{} if ( $@ ) … でエラー対策してるつもりなんだけどトラブル時のエラーがうまく動いていないような。今回あらためて、Perl try-catch で検索したら、Perl 5.34 で try-catch が実験的にサポートされているらしいので使ってみた。

use feature qw( try ) ;
no warnings "experimental::try" ;
:
try {
  $feed->merge( $rss ) ;
} catch( $e ) {
  print "catch $e" ;
}
# eval { $feed->merge( $rss ) ; } ;
# if ( $@ ) {
#    warn "..." ;
# }

スクリプト言語の比較

Raspberry Pi で、自宅内の温湿度管理とか色々やっていて、shell や perl や python などのスクリプトを使っているけど、ただでさえ遅い Raspberry-Pi だし、少しでも軽く動いてほしくて、lua なども使っている。

でも、shell だと、bash で書いているけど、高機能な分だけ遅いし、少しでも軽くなればと、インストールされているスクリプト言語のサイズを改めて比較をしてみた。

$ ls -al <いろいろ>
-rwxr-xr-x 1 root root   14000  1月  2  2021 /usr/bin/lua50
-rwxr-xr-x 1 root root   91904 12月 10  2020 /bin/dash
-rwxr-xr-x 1 root root   92292 12月 22  2018 /bin/sed 
-rwxr-xr-x 1 root root  120704  2月 17  2020 /usr/bin/mawk
-rwxr-xr-x 1 root root  133048  8月  1  2016 /usr/bin/lua5.1
-rwxr-xr-x 1 root root  974312  3月 28  2022 /bin/bash
-rwxr-xr-x 2 root root 3201036  9月 25  2021 /usr/bin/perl5.32.1
-rwxr-xr-x 1 root root 4703672  3月 12  2021 /usr/bin/python3.9

個人的には、軽いスクリプトというと、sed < awk < lua < bash < perl < python というイメージで使い分けをしていた。

しかし、これを見ると、bash と dash で10倍の差、軽くなればと使っていた lua だけど、lua5.1 と lua50 でも 10 倍の差がある。perl だと bash の 3倍、python だと bash の5倍。バイナリのサイズが単純に処理速度に反映される訳ではないけど、これを見る限り、自分で書いている手抜きスクリプトであれば、dash や lua50 で動かした方がよさそうだな。

また、下手に Perl を使うぐらいなら、bash の中で sed や awk を交えながらスクリプトを書くことも多いけど、下手に bash の中で sed や awk をガシガシ使ったら、あんまり早くなさそうだな。

これからは、lua50 < dash < sed , awk < bash < perl < python かな。

RPi-MZ80Cのボード入替え

Raspberry-Pi による ミニチュア MZ80C のボードを入れ替えして、表示部分も入替え。
{CAPTION}
以前より導入していたBME280の温度・湿度・気圧に加え、不快指数とYahoo天気の天気情報を表示するようにしてみた。

Raspberry-Pi MZ80C のボード差し替え

RPi model A+ が異常

以前に購入した Raspberry-Pi model A+ の MZ80C だけど、ボードがおかしくなっているのか、CPU 負荷がアイドル状態なのに 100% となっている。同様の Rapberry Pi と処理速度も変わらないし、何か変。RPi3 のボードに比べると処理速度も遅いし、RPi 3 model A+ のボードが同じ RPi3 model B より割安なのでボード差し替えをやってみる。

RPi 3 model A+ に差し替え

せっかくだし、表示部分も I2C 接続の SSD1306 の OLED Display を買う。

https://github.com/adafruit/Adafruit_Python_SSD1306

((( SSD1306 )))
GND VCC SCL SDA
黒  白  灰  紫

((( BME280 )))
VDD GND NC  SDI SDO SCK
VDD GND --  SDA --- SCL
白  赤  ×  黄 ×   青

((( Raspberry-Pi )))
3.3 SDA SCK × GND

BME280, Adafruit SSD1306を使えるように

この RPi は、2Fのトイレに設置して、2Fの廊下全体の温度を測っていた。なので、載せ替えした RPi にも同様の機能を移植。

なんとか動くようになったかな。

ただ、syslog を見ると、電源電圧不足の警告が出ているし、たまに繋がらなくなる。確認すると再起動してる。USB電源アダプタ電流とれるやつに差し替えが必要だな。

自宅サーバトラブル

エコキュートのメモを書き残していたら、急に自宅サーバに繋がらなくなる。ping も通らない。

デバイスが見つけられなくなり、起動できなかったけど BIOS の boot device を色々触っていたら、なぜだか復帰。

一時的なトラブルならいいけど、サーバ故障の予兆かもしれないので、メモとして残す。

そろそろ、サーバも更新の準備をしておくべきかも。

 

Raspberry Pi の bullseye 更新

いつも大きい更新をかける時は、依存関係でトラブルから、利用頻度の低いパッケージを削除したり、重要なパッケージだけ個別に更新していたけど、”apt upgrade –without-new-pkgs” は、便利なコマンド。これなら、ディスク容量が少ない Raspberry-Pi でも途中で容量不足で止まったりといった心配も少ない。

((( busterで更新 )))
$ sudo aptitude update ; sudo aptitude safe-upgrade

((( bullseyeの登録 )))
$ sudo vi /etc/apt/sources.list.d/11-bullseye.list
deb http://raspbian.raspberrypi.org/raspbian/ bullseye main contrib non-free rpi
deb-src http://raspbian.raspberrypi.org/raspbian/ bullseye main contrib non-free rpi

((( 最小限アップグレード )))
$ sudo aptitude
$ sudo apt upgrade --without-new-pkgs
$ sudo aptitude safe-upgrade

2台まとめての buster→bullseye 更新でいくつか、自分の家専用の処理が動かなくなったが、ボチボチと修正し復帰かな。

リモート監視 nagios-nrpe を使ってみる

Raspberry-Pi で WiFi スキャンをさせたいけど、警告を出すために raspberry-pi 側に nagios4 のような本格的な監視システムを入れるのは資源のムダに思えたので、軽量な監視とすべく、リモート監視用の nagios-nrpe-server を使ってみた。

メインサーバ                port=5666 リモート    監視プラグイン
  nagios4 ----> check_nrpe ------------> nrpe ----> check_root
            nagios-nrpe-plugin     nagios-nrpe-server

nrpe は リモートの監視プラグインを check_nrpe と nagios-nrpe-server が経由して呼出してくれる。

リモートの監視側

nagios-nrpe-server をインストールして、監視サーバからの接続を許可する。インターネット経由で監視するなら、5666 ポートが通るようにファイアウォールの設定が必要。

((( 必要パッケージのインストール )))
$ sudo aptitude install nagios-nrpe-server

((( /etc/nagios/nrpe.cfg )))
# 監視サーバからの接続を許可
allowed_hosts=127.0.0.1,::1,192.168.xx.00/24
                           ~~~~~~~~~~~~~~~~~(追加)
((( /etc/nagios/nrpe.d/enabled.cfg )))
# 監視するためのチェック処理を登録。nrpe.cfg から nrpe.d/*.cfg に設定を移動
command[check_root]=/usr/lib/nagios/plugins/check_disk -w 20% -c 10% -p /
command[check_load]=/usr/lib/nagios/plugins/check_load $ARG1$

((( /etc/default/nagios-nrpe-server )))
# 自宅内のような閉じた中でSSLが不要の場合
NRPE_OPTS="-n"
((( nagios-nrpe-server を再起動 )))
$ sudo systemctl restart nagios-nrpe-server

メインの監視サーバ側

nrpe用のプラグインをインストールすると、/etc/nagios-plugins/config/check_nrpe.cfg や /usr/lib/nagios/plugins/check_nrpe を入れてくれる。

((( 監視側にnrpe用のプラグインを追加 )))
$ sudo aptitude install nagios-nrpe-plugin  # nagios or icinga はインストール済み

((( nrpe の入ったリモートが呼び出せるか確認 )))
$ /usr/lib/nagios/plugins/check_nrpe -H リモート -c check_root
DISK OK - free space: / 21321 MB (74% inode=86%);| /=7363MB;23944;26937;0;29930

((( /etc/nagios-plugins/config/check_nrpe.cfg )))
# nagios/icingaなどのcommand設定の確認
# this command runs a program $ARG1$ with no arguments and enables SSL support
define command {
        command_name    check_nrpe
        command_line    /usr/lib/nagios/plugins/check_nrpe -H $HOSTADDRESS$ -c $ARG1$
}
# this command runs a program $ARG1$ with no arguments and disables SSL support
define command {
        command_name    check_nrpe_nossl
        command_line    /usr/lib/nagios/plugins/check_nrpe -H $HOSTADDRESS$ -c $ARG1$ -n
}

((( nagios4 のサービス監視に check_nrpe を呼出す設定を追加 )))
define service{
    use                 local-service
    host_name           リモート
    service_description DISK
    check_command       check_nrpe!check_root
    # check_command     check_nrpe_nossl!check_root  # SSLなしで設定した場合
}

((( nagios4 を再起動 )))
$ sudo systemctl restart nagios4

nagios4 で監視ができるようになったので、温湿度センサーや空気品質センサーの確認も nrpe 経由に変更してみた。

WiFiスキャンをさせてみた

自宅内のネットワークに繋がらない時があって悩んだら、外で使っていたモバイルルータがつけっぱなしで、自宅内ネットワークのサービスに接続できないのが原因だったりする。パケットも無駄に消費するので、自宅内でモバイルルータが動いていたら警告させるようにしたい。

wifi scan

メインサーバは有線だけなので、有線LAN接続で WiFi が空いている Raspberry-Pi で監視させてみた。

$ sudo iw dev wlan0 scan | grep "SSID: ルータのSSID"

最初は homebridge の homebridge-cmdswitch2 の state_cmd に仕込んでみたけど、モバイルルータが動いていたら警告してほしい。Siri のオートメーション経由で警告することもできるかもしれないけど、スマホに頼る形になるなぁ。

nagios で警告させたいけど、raspberry-pi に nagios を入れるのは資源のムダに思える。ということで、Raspberry-Pi には nagios の監視をリモートで呼び出す nagios-nrpe-server を 入れて、上記 iw コマンドを動かす check スクリプトを書いてみた。

check_iwscan

nagios-nrpe-server から呼出す際に、Raspberry-Pi で動かすのもあるし、OS 負荷が軽くなるように Lua で書いてみた。

#!/usr/bin/lua

-- 見つけるべきSSID
local check_list = {}
check_list[ "tsaitoh.net" ] = "ok"
check_list[ "tsaitoh.net_e5785" ] = "warning"
check_list[ "tsaitoh.net_hwd14" ] = "critical"

-- 見つけたSSID毎の数
local count = {}
count[ "ok" ] = 0
count[ "warning" ] = 0
count[ "critical" ] = 0

-- スキャン結果を処理
local handle = io.popen( "/usr/bin/sudo /sbin/iw dev wlan0 scan" , "r" )

if handle then
   for line in handle:lines() do
      -- SSID を抽出
      ssid = string.match( line , "^%s*SSID: (.+)$" )
      if ssid then
         -- SSID のカウント
         local lv = check_list[ssid]
         if lv then
            count[lv] = count[lv] + 1
         end
         -- print( ssid ) ;
      end
   end
   handle:close()
end

-- カウント結果に応じたexit値を決める
local status = 0
local st_mess = "Ok"

if count["critical"] > 0 then
   status = 2
   st_mess = "Critical"
elseif count[ "warning" ] > 0 then
   status = 1
   st_mess = "Warning"
end

-- 結果の表示
print( string.format( "IWSCAN %s - ok:%d/warn:%d/critical:%d" ,
                      st_mess , count["ok"] , count["warning"] , count["critical"] ) )
os.exit( status )

MQTTの設定

MQTTとホームオートメーション

自宅サーバで、ホームオートメーションもどきで遊んでいるけど、デバイスとのデータのやり取りは軽量の MQTT プロトコルがあるらしい。M5Stack ATOM Lite などからの情報を上げる時などで遊べそうなので、実験してみよう。

# 現状では センサー側の Raspberry-Pi では inetd.conf などで問合せポートにアクセスがあったら測定値を echo バックするような設定となっている。

mosquittoのインストール

でもひとまずは、MQTT ブローカー のオープンソース実装 mosquitto をインストール。

ブローカーとなる Raspberry-Pi には、mosquitto, mosquitto-clients をインストール。

((( ブローカーで mosquitto のインストール )))
$ sudo aptitude install mosquitto mosquitto-clients

温湿度センサーを搭載したパブリッシャー側の Raspberry-Pi には、mosquitto-clients のみをインストール。最終的には Net::MQTT::Simple を使うようにしたから不要だけど動作試験には使える。

((( パプリッシャー側は mosquitto-client だけ入れる )))
$ sudo aptitude install mosquitto-clients

mosquitto はデフォルトで外部接続を受けないので、外部接続の設定を追加。Debian流で /etc/mosquitto/conf.d/00-remote-access.conf にリモートアクセスを受ける設定を追記。

# listener<tab>1883 だとエラーになった。項目区切りで tab 使えんのか???

後のブラウザで確認するために、websocket の機能も設定しておく。

((( 最小限の生接続でひとまず実験 )))
$ sudo vi /etc/mosquitto/conf.d/00-remote-access.conf
listener        1883  # 1883 ポートで受信
allow_anonymous true  # パスワード無し

((( Websocket の設定 )))
$ sudo vi /etc/mosquitto/conf.d/10-websocket.conf
listener        15675
protocol        websockets

((( mosquitto を再起動 )))
$ sudo systemctl restart mosquitto

((( パスワード認証を使うなら )))
$ sudo mosquitto_passwd -c /etc/mosquitto/passwd mqtt

$ sudo vi /etc/mosquitto/mosquitto.conf
(先頭に)
per_listener_settings true

$ sudo vi /etc/mosquitto/conf.d/00-remote-access.conf
(追記)
password_file /etc/mosquitto/passwd

$ sudo systemctl restart mosquitto

MQTTの基本的な導通テスト

まずは基本的な導通テスト

((( ブローカー側 )))
$ sudo mosquitto_sub -d -t /sensor/place/temperature/host

((( パブリッシャー側 )))
$ mosquitto_pub -h ブローカーホスト名 -d -t /sensor/place/temperature/host -m 12.34

((( 実験結果 )))
$ sudo mosquitto_sub -d -t /sensor/place/+/host
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending SUBSCRIBE (Mid: 1, Topic: /sensor/place/+/host, QoS: 0, Options: 0x00)
Client (null) received SUBACK
Subscribed (mid: 1): 0
Client (null) received PUBLISH (d0, q0, r0, m0, '/sensor/place/temperature/host', ... (4 bytes))
12.34

パブリッシャー側のプログラム

外気?温度(トイレ)で温度湿度を測っている Raspberry Pi の温度情報更新処理の中に Perl でブローカー宛にパプリッシュする処理を埋め込むのなら、Net::MQTT::Simple で書くのが簡単。
Net::MQTT::Simple が HTTP::Tiny を使うけど、CPAN でインストールするパッケージは最小にしたいので、HTTP::Tiny は apt-get でインストール。

((( HTTP::Tiny をインストール )))
$ sudo aptitude install libhttp-tiny-perl

((( CPANで Net::MQTT::Simple をインストール )))
$ sudo perl -MCPAN -e shell
cpan[..]> install Net::MQTT::Simple

retain(…) でメッセージを送る際に、複数の項目を連続で送る場合は、各項目毎に 30msec 50msec ほどの遅延が必要だった。
# パブリッシャー側の問題?/ブローカー側の問題? 20msec だと後続の retain が失敗した。30msecだと最後の retain が失敗(不安定)

use Net::MQTT::Simple;
use Time::HiRes 'usleep' ;
my $mqtt = Net::MQTT::Simple->new("ブローカーホスト名") ;       # brokerのホスト名

$mqtt->retain( "/sensor/place/temperature/host" => "12.3" ) ; # センサーの値を送る時
usleep( 50000 ) ;                                             # 50msecの遅延が必要
$mqtt->retain( "/sensor/place/humidity/host" => "67.8" ) ;    # センサーの値を送る時
usleep( 50000 ) ;
$mqtt->retain( "/sensor/place/pressuore/host" => "1023.4" ) ; # センサーの値を送る時

ひとまずサブスクライバの代わりに Web ブラウザで mosquitto の結果を見るための HTML , js をダウンロード。

$ cd /var/www/html
$ sudo mkdir mqtt
$ cd mqtt
$ sudo wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-web-mqtt-examples/master/priv/echo.html
$ sudo wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-web-mqtt-examples/master/priv/mqttws31.js

echo.html の受信するトピックの設定を修正。

    ((( 84行目 )))
        var print_first = pipe('#first', function(data) {
            message = new Paho.MQTT.Message(data);
            message.destinationName = "/sensor/place/+/host"; // トピックを修正
            debug("SEND ON " + message.destinationName + " PAYLOAD " + data);
            client.send(message);
        });

    ((( 108行目 )))
        var options = {
            timeout: 3,
            keepAliveInterval: 30,
            onSuccess: function () {
                debug("CONNECTION SUCCESS");
                client.subscribe("/sensor/place/+/host", {qos: 1}); // トピックを修正
            },
            onFailure: function (message) {
                debug("CONNECTION FAILURE - " + message.errorMessage);
            }
        };

Google 検索

My Google   Yahoo

Microsoft

ファンサイト