Rasbianのディスクイメージは、2つのパーティションになっていて、2つ目がOSが使うルートパーティションである。それをディスクとしてマウントすれば、中身の編集を行うことができる。
その際、2つめのパーティションの先頭セクタ(単位はバイト数)を引数に与える必要がある。そのためfdisk -lの出力からそれを切り出し、mountのオプションに加えてマウントする。
ただし、イメージをSDに焼くコンピュータ上で行うのでなければあまり効率的ではない。(Macならbashが入っているので使えるかも。Windowsでも最近はbashが入っているので試す価値はある。)
#!/bin/bash
IMG_FILE=$1
MOUNT_DIR=$2
# ディスクイメージの先頭セクタを得る
TMP=$(fdisk -l $IMG_FILE | sed -r "s/^.*img2\s+([0-9]+)\s+.*$/\1/" | tail -1)
START_SEC=$((TMP*512))
# ディスクイメージをマウント
mount -t ext4 -o loop,offset=${START_SEC} ${IMG_FILE} ${MOUNT_DIR}
if [ $? != 0 ]; then
echo "mount failed"
exit
fi
loopデバイスのマウントはroot権限でしか行えないので、sudoで実行する。
利用例:
8tops上でimageファイルを/home/toyoki/mnt/img1にマウントする場合
sudo ./mount_raspi_img.sh /nfs/raspi-img/raspi_toyoki-lab.20190506.pi3.img /home/toyoki/mnt/img1
(mnt/img1は予めmkdirしておく。)
さしあたって、センサ個々に設定を変えるに必要があるのは次の2つである。
上記のようにマウントして、この2つを書き換えるシェルスクリプト例
(パソコンの上で行う場合の注意)
以下のスクリプトは8tops上で実行するよう変数を設定してある。
#!/bin/bash
# 引数 [-d 作業用マウントディレクトリ] [-s サーバールート] -n 端末名 -a エリア名 ディスクイメージファイル名
usage_exit() {
echo "Usage: $0 [-d mount_dir] [-s server_root] -n sensor_name -a area image_file" 1>&2
exit 1
}
MOUNT_DIR=/mnt/tmp # imageファイルのマウントポイント(コマンドライン引数で上書き)
NAME2NUM_SCR=./name2portNum.py # 名前→ポートプログラム
PORT_LIST_DIR=./port_nums # サーバ上の既存端末リストの在り処
AREA_NAME="" # 地域名 ex. kofu, fuefuki, hakushu, ...
SERVER_ROOT="raspimngr@8tops.yamanashi.ac.jp:~/pcap_data/"
# 引数処理
while getopts "d:n:a:s:h:" OPT
do
case $OPT in
d) MOUNT_DIR=$OPTARG
;;
n) SENSOR_NAME=$OPTARG
;;
a) AREA_NAME=$OPTARG
;;
s) SERVER_ROOT=$OPTARG
;;
h) usage_exit
;;
\?) usage_exit
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 1 ]; then
IMG_FILE=$1
else
usage_exit
fi
# port番号重複の有無チェック
SEARCH_NUM=$(${NAME2NUM_SCR} ${SENSOR_NAME} | head -1 | tr -d '\n')
RESULT=$(ls ${PORT_LIST_DIR} | grep ${SEARCH_NUM})
if [ "${RESULT}" != "" ]; then
echo "名前 ${SENSOR_NAME} が使うポート番号 ${SEARCH_NUM}はすでに存在します。"
exit
fi
# ディスクイメージの先頭セクタを得る
TMP=$(fdisk -l $IMG_FILE | sed -r "s/^.*img2\s+([0-9]+)\s+.*$/\1/" | tail -1)
START_SEC=$((TMP*512))
# ディスクイメージをマウント
mount -t ext4 -o loop,offset=${START_SEC} ${IMG_FILE} ${MOUNT_DIR}
if [ $? != 0 ]; then
echo "mount failed"
exit
fi
# **設定作業**
# port_nameの書き換え
${NAME2NUM_SCR} ${SENSOR_NAME} > ${MOUNT_DIR}/home/pi/conf/port_id.txt
# area名 (scp_pcaps.pyの送信先サブディレクトリ名)
echo ${AREA_NAME} > ${MOUNT_DIR}/home/pi/conf/area_name.txt
# サーバ//pcapディレクトリ名 (scp_pcaps.pyの送信先サーバ/ディレクトリ)
echo ${SERVER_ROOT} > ${MOUNT_DIR}/home/pi/conf/server_root.txt
# /var/wifi_pr/の掃除
/bin/rm ${MOUNT_DIR}/var/wifi-pr/*.pcap > /dev/null 2>&1
# 書き込み内容を表示
echo "以下を書き込みました. (エリア名、ポート、センサ名、送信先ディレクトリ)"
cat ${MOUNT_DIR}/home/pi/conf/*.txt
# 終了:アンマウント
umount ${MOUNT_DIR}