Raspberry Pi4をNAS用途、DiscordBot用に稼働させているが、どんな設定をしたか忘れないために記録する。
環境は以下の通りである。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm
OS書き込み
RaspberryPi ImagerでOSを書き込む前にWi-Fiの設定やパスワード、SSHの有効化を行っておく。
自動ログインの設定
ラズパイの電源を入れてログインする。
sudo raspi-config
-
STEP1
System Options
-
STEP2
Boot / Auto Login Select boot into desktop or command line
-
STEP3
Console Autologin Text console, automatically logged in as '***' user
再起動して確認する。
コンソールの文字の大きさ
小型のディスプレイを使用している場合は、ディスプレイの文字の大きさが小さくなって見えにくいため、大きさを変更する。
Wi-Fiパワーマネージメント
初期状態ではONになっており、速度が遅かったり、切断の原因になるためOFFにする。
sudo iwconfig wlan0 power off
sudo nano /etc/rc.local
#この部分を [exit 0] の上に追記
iwconfig wlan0 power off
exit 0
rc.localに記述することで再起動してもpower managementをOFFにすることができる。
IPの固定化
ラズパイのネットワークの設定には「NetworkManager」を使用する。
「dhcpcd」も使えるみたいだが、上手くいかなかったのでアンインストールした。
初期状態ではコネクション名が長いため、分かりやすい名前に変更しておく。
「Wired connection 1」を「eth0」に変更する場合は以下の通り。
sudo nmcli connection modify 'Wired connection 1' connection.id eth0
sudo nmcli connection modify eth0 ipv4.addresses 固定したいIP/24
sudo nmcli connection modify eth0 ipv4.gateway デフォルトゲートウェイ
sudo nmcli connection modify eth0 ipv4.dns 8.8.8.8,8.8.4.4
sudo nmcli connection modify eth0 ipv4.method manual
sudo nmcli connection up eth0
#設定の確認
nmcli -f ipv4 connection show eth0
#設定ファイルの場所
sudo nano /etc/NetworkManager/system-connections/'Wired connection 1.nmconnection'
Wi-Fiも固定IPを設定できる。
sudo nmcli connection modify preconfigured ipv4.method manual ipv4.addresses 固定したいIP/24 ipv4.gateway デフォルトゲートウェイ ipv4.dns 8.8.8.8,8.8.4.4
sudo nmcli device disconnect wlan0
sudo nmcli device connect wlan0
#設定ファイルの場所
sudo nano /etc/NetworkManager/system-connections/preconfigured.nmconnection
しかし、実際にラズパイを運用する上でWi-Fiは遅く、不安定なため、無効化した方が良い。
合わせてBluetoothも使用しないため、完全に無効化しておく。
sudo nano /boot/firmware/config.txt
/boot/firmware/config.txt
#末尾に以下を追記
dtoverlay=disable-bt
dtoverlay=disable-wifi
再起動してWi-Fiが起動していないことを確認する。
#接続状況の確認
nmcli device status
nmcli connection show
ネットワーク速度テスト
速度がどのくらい出るのか調べたいときがあるのでインストールしておく。
sudo apt install speedtest-cli
#実行コマンド
speedtest-cli
Retrieving speedtest.net configuration...
Testing from So-net (****)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by Macarne LLC (Tokyo) [**** km]: **** ms
Testing download speed................................................................................
Download: 91.23 Mbit/s
Testing upload speed......................................................................................................
Upload: 90.40 Mbit/s
このように簡単に速度テストができるようになる。
SWAPの無効化
Raspberry Pi4では搭載されているメモリが十分な場合、SWAPの出番がないのでOFFにする。
SWAPをOFFにすることでSDカードの寿命を延ばす効果に期待したい。
#SWAPの確認
free -h
sudo swapoff --all
sudo systemctl stop dphys-swapfile
sudo systemctl disable dphys-swapfile
systemctl status dphys-swapfile
free -h
USBメモリなどのアンマウント
普通にアンマウントしようとすると target is busy となり、できないことが多い。
-l のオプションをつけることで強制的にアンマウントする。
sudo umount -l /dev/sda1 #例
USBドライバの設定(UASの無効化)
lsusb -t
=> Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
|__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
UASが悪さをすることがあるようなので、その場合は以下の設定を行う。
lsusb
#IDをメモする
=> Bus 002 Device 002: ID ****:**** JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
sudo nano /boot/firmware/cmdline.txt
#内容はスペースで分ける(絶対に改行しない)
=> usb-storage.quirks=****:****:u dwc_otg.lpm_enable=・・・
sudo reboot
#確認
lsusb -t
=> Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
|__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
Driver=*** の部分が uas から usb-storage に変更されていることを確認する。
sudo apt update時のエラー
sudo apt update
~省略~
Some index files failed to download. They have been ignored, or old ones used instead.
このようにエラーが出る場合に以下の対応を行う。
#コマンド
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf > /dev/null
Samba(NAS化)
ラズパイに接続した外部メモリをNASとして使用したいのでSambaをインストールして設定します。
#儀式
sudo apt update
sudo apt -y upgrade
#インストールとディレクトリの作成、権限の付与
sudo apt install samba
sudo mkdir /nas
sudo chmod 777 /nas
#smb.confの設定
sudo nano /etc/samba/smb.conf
#[global]に以下を追記
browseable=no
#末尾に以下を記述
[raspberrypi]
comment = Raspberry Pi
path = /nas
guest ok = no
read only = no
browsable = yes
#ユーザーとパスワードの設定
sudo smbpasswd -a USERNAME
#Samba再起動
sudo systemctl restart smbd
NFSサーバー
前項で設定したSambaで共有されたフォルダに別のラズパイからアクセスしたい場合があるのでNFSサーバーを設定します。
Sambaをインストールしているラズパイ側
#儀式
sudo apt update
sudo apt -y upgrade
#インストール
sudo apt install nfs-kernel-server
#設定
sudo nano /etc/exports
#以下を追記 - Sambaのフォルダ 別のラズパイのIP(rw,sync,no_subtree_check)
/nas 192.168.*.**(rw,sync,no_subtree_check)
別のラズパイ側
#儀式
sudo apt update
sudo apt -y upgrade
#インストール
sudo apt install nfs-common
#NFSのマウントポイントを作成、権限の付与
sudo mkdir /home/pi/***
sudo chmod 777 /home/pi/***
#マウント実行 - SambaがインストールされているラズパイのIP:共有フォルダ このラズパイのマウントポイント
sudo mount -t nfs 192.168.*.**:/nas /home/pi/***
ディスクの速度計測
ラズパイに接続しているUSBメモリ等の外部ディスクの読み書き速度を計測したいときがあるためインストールする。
sudo apt install -y hdparm
#測定
sudo hdparm -t /dev/sda1
=>/dev/sda1:
Timing buffered disk reads: 344 MB in 3.01 seconds = 114.33 MB/sec
PrometheusとGrafana
追記
詳しく検証してないので断言できないが、PrometheusとGrafanaをインストールするとラズパイ起動時に「networkmanager-wait-online.service」で待たされるようになる。
大変便利なツールだが、CPU使用率、温度、メモリ使用率くらいしか見ておらず、わざわざインストールする必要がないと判断し、現在は使用していない。
RaspberryPiのモニタリングは必要であるため、代わりとなるプログラムをPythonで記述する。(次項)
ラズパイの管理を行う上で様々な情報が見たい場合があるので、監視ツールとしてインストールする。
#Prometheusのインストール
sudo apt install -y prometheus prometheus-node-exporter
#依存パッケージのインストール
sudo apt install -y apt-transport-https software-properties-common wget
#GPGキーのインストール
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
#安定リリース版のリポジトリを追加
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
#Grafanaのインストール
sudo apt update
sudo apt install grafana-enterprise
#Grafanaの起動
sudo systemctl daemon-reload
sudo systemctl start grafana-server
sudo systemctl status grafana-server
#Grafanaの自動起動の有効化
sudo systemctl enable grafana-server.service
後に、PrometheusのURLをGrafanaに紐づけてダッシュボードを作成する。
しかし、このままでは外出先からアクセスできないため、少し不便に感じる。
外出先からアクセスできるようにするための方法が難しく、セキュリティ面において不安が残るためDiscordBotを使用する。
import discord
import cv2
import time
from selenium import webdriver
from selenium.webdriver import Chrome, ChromeOptions
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
import pyvirtualdisplay
client = discord.Client(intents=discord.Intents.all())
@client.event
async def on_ready():
print(f'We have logged in as {client.user}')
@client.event
async def on_message(message):
if message.author == client.user:
return
#####監視カメラ機能#####
#WEBカメラの画像
if message.content.startswith('$image'):
camera = cv2.VideoCapture(0)
ret, img = camera.read()
path = "保存先のパス"
cv2.imwrite(path, img)
camera.release()
cv2.destroyAllWindows()
await message.channel.send(file=discord.File(path))
########################
#コマンド名
if message.content.startswith('$grafana'):
display = pyvirtualdisplay.Display(visible=0, size=(1980, 1080))
display.start()
url = 'ここにURL(例:温度のパネルとか)'
options = ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--headless')
driver = Chrome(executable_path='/usr/bin/chromedriver', options=options)
driver.get(url)
driver.implicitly_wait(5)
#パスワード画面
user_elem = driver.find_element(By.NAME, 'user')
pass_elem = driver.find_element(By.NAME, 'password')
user_elem.clear()
pass_elem.clear()
#ユーザー名とパスワード
user_elem.send_keys('**********')
pass_elem.send_keys('**********')
driver.implicitly_wait(5)
#ログインボタンのクラス名
login_btn = driver.find_element(By.CLASS_NAME, '**********')
login_btn.click()
#パネルのクラス名
driver.implicitly_wait(5)
driver.find_element(By.CLASS_NAME, '**********')
#ズーム率とスクショの保存先
driver.execute_script("document.body.style.zoom='50%'")
driver.save_screenshot('ここにパス')
driver.close()
display.stop()
#スクショのパス
await message.channel.send(file=discord.File('ここにパス'))
#Discord Botのトークン
client.run('Discord Bot Token')
このPythonファイルの一行目に以下を記述する。
#!/usr/bin/python3
このPythonファイルをラズパイの起動時にサービスとして起動させたいため、サービスファイルを作成する。
サービス名は任意で設定可能です。今回は「raspberrypi」としています。
cd /usr/lib/systemd/system
sudo nano raspberrypi.service
[Unit]
Description=Discord Bot #コメント
[Service]
ExecStart=/home/pi/bot.py #フルパスで記述
Restart=always
Type=simple
[Install]
WantedBy=multi-user.target
念のためPythonファイルとサービスファイルに最高権限を与えます。
sudo chmod 777 /ここにパス
#サービスの起動
sudo systemctl start raspberrypi.service
#サービスの自動起動
sudo systemctl enable raspberrypi.service
このようにDiscord Botを経由することで、いつでも外出先からでもパネルの情報を画像で知ることができる。
コマンドの数を増やせば取得できる情報も増やすことができるが、性能の低いラズパイを使用している場合は応答速度が遅くなったり、処理が重くなる可能性があるため注意する。
Raspberry Pi4 8GBモデルでは問題なく動作した。
パネルの情報が変化しない場合は、パネルの共有URLの作成前にリフレッシュ間隔を5sに変更することで改善される。
ラズパイのモニタリング(Python)
特に監視したい項目は以下の通りである。
今回は他にも「CPUの周波数」「CPUの電圧」も記録していく。
UPTime(合計起動時間)の記録については個別でPythonファイルを作成し、サービス化する。
その他の項目に関しては1つのPythonファイルに記述し、サービス化する。
スプレッドシートを作成し、「拡張機能」から「Apps Script」をクリックしてエディタを開き、以下を記述する。
function doGet(e) {
//データ
var dt = e.parameter.dt;
var cpu_temp = e.parameter.cpu_temp;
var cpu_freq = e.parameter.cpu_freq;
var cpu_voltage = e.parameter.cpu_voltage;
var mem = e.parameter.mem;
var uptime = e.parameter.uptime;
//Activeになっているsheetを取得
var sheet = SpreadsheetApp.getActiveSheet();
//書き込み
sheet.appendRow([dt, cpu_temp, cpu_freq, cpu_voltage, mem, uptime]);
}
「デプロイ」から「新しいデプロイ」→「ウェブアプリ」→アクセスできるユーザーを全員に設定する。
これにより、URLを知っている全員がアクセス可能な状態になるため、URLの管理には注意する。
作成したウェブアプリのURLをメモする。
事前にラズパイの「uid」と「gid」の確認をしておく。
grep pi /etc/passwd
=>user:x:****:****:,,,:/home/pi:/bin/bash
UPTimeのPythonプログラムを作成する。
このプログラムではUPTime記録用のCSVを外部メモリに記録するようにしているため、起動時にマウントポイントに接続するよう、「subprocess」でシェルコマンドを実行する。
#!/usr/bin/python3
import time
import csv
import subprocess
#接続したままの外部メモリを起動時にマウントする(UUIDは外部メモリのもの)
command_1 = "sudo -S mount -o owner,uid=****,gid=****,utf8,flush UUID='*****' /home/pi/***マウントポイント"
ret_1 = subprocess.run(command_1, shell=True, capture_output=True, text=True)
#UPTimeを記録する間隔
interval = 10
path = 'UPTime記録用CSVのパス'
while True:
with open(path) as f:
reader = f.read()
# print(reader)
uptime = int(reader) + interval
with open(path, 'w') as f:
writer = csv.writer(f)
writer.writerow([uptime])
time.sleep(interval)
今回はCSVに記録して定期的に書き換える方法にした。
注意点として、CSVファイルは事前に作成しておき、「0」とだけ記述しておく。
次に、その他のモニタリングを行うプログラムを作成する。
#!/usr/bin/python3
import subprocess
import datetime
import time
import sys
import re
import psutil
import requests
import subprocess
#接続したままの外部メモリを起動時にマウントする(UUIDは外部メモリのもの)
command_1 = "sudo -S mount -o owner,uid=****,gid=****,utf8,flush UUID='*****' /home/pi/***マウントポイント"
ret_1 = subprocess.run(command_1, shell=True, capture_output=True, text=True)
url = 'ここにデプロイしたURL'
#スプレッドシートに記録するためのリクエスト用URLを作成
def mkUrl(url, dt, cpu_temp, cpu_freq, cpu_voltage, mem, uptime):
newUrl = url + '?'
newUrl += 'dt=' + str(dt) + '&'
newUrl += 'cpu_temp=' + str(cpu_temp) + '&'
newUrl += 'cpu_freq=' + str(cpu_freq) + '&'
newUrl += 'cpu_voltage=' + str(cpu_voltage) + '&'
newUrl += 'mem=' + str(mem) + '&'
newUrl += 'uptime=' + str(uptime)
return newUrl
while True:
#DateTime
dt = datetime.datetime.now().replace(microsecond=0)
#CPU Temp(単位:℃)
temp = subprocess.run('vcgencmd measure_temp', shell=True, encoding='utf-8', stdout=subprocess.PIPE).stdout.split('=')
temp = temp[1].split("'")
cpu_temp = temp[0]
#CPU Freq(単位:GHz)
freq = subprocess.run('vcgencmd measure_clock arm', shell=True, encoding='utf-8', stdout=subprocess.PIPE).stdout.split('=')
cpu_freq = int(freq[1].replace('\n', '')) / 1000000000
#CPU Voltage(単位:V)
volt = subprocess.run('vcgencmd measure_volts', shell=True, encoding='utf-8', stdout=subprocess.PIPE).stdout.split('=')
volt = volt[1].split('V')
cpu_voltage = volt[0]
#CPU Mem(単位:)
mem = psutil.virtual_memory().percent
#UPTime(単位:秒)
with open('UPTime記録用CSVのパス') as f:
reader = f.read()
uptime = reader
#データの送信
upUrl = mkUrl(url, dt, cpu_temp, cpu_freq, cpu_voltage, mem, uptime)
requests.get(upUrl)
#プログラムを実行する間隔(15分)
time.sleep(900)
このプログラムで「UPTime」の記録も一緒にスプレッドシートに記録する仕組みになっている。
プログラム完成後は前項で記載してあるように、各Pythonファイルをサービス化して自動起動を有効にする。
実際に記録されたスプレッドシートは以下の通りである。
一行目のヘッダーは事前に入力したものである。
0 件のコメント:
コメントを投稿