Raspberry Pi ZERO Ranger + kpartx

Raspbian imgをマウントするためZEROにkpartxを導入しました。今回はRangerから利用してみたいと思います。
新規にインストールするカードは基本ZEROから作成する予定ですがRaspbian imgを直接編集することでいろいろ応用することができます。
以前pcmanfmに設定した記事と基本同じです。

kpartx

# apt install kpartx

kpartxの基本操作は以下のとおり

# kpartx -va 2018-11-13-raspbian-stretch-lite.img
add map loop0p1 (254:0): 0 89854 linear 7:0 8192
add map loop0p2 (254:1): 0 3547136 linear 7:0 98304
# ls /dev/mapper
control  loop0p1  loop0p2
# mount /dev/mapper/loop0p2 /mnt
---
# umount /mnt
# kpartx -d 2018-11-13-raspbian-stretch-lite.img
loop deleted : /dev/loop0
# ls /dev/mapper
control

loop deviceの取り外しはこんな方法もあります。
参考 https://seesaawiki.jp/w/kou1okada/d/Linux%20-%20loop%20device

# dmsetup remove loop0p2
# losetup -d /dev/loop0

マウント
ダウンロードしたRaspbian imgは/home以下に適当にディレクトリを作成、展開しました。

# mkdir loop0p1 boot用
# mkdir loop0p2 rootfs用
2018-11-13-raspbian-stretch.imgをコピーした2018-11-13-stretch-pi3.imgを編集します。

ranger
rangerのインストールについては以前の記事を参照
kpartxの実行、マウントはrangerのrifle.confを利用して実行します。
~/.config/ranger/rifle.conf

ext img = sudo kpartx -va "$@" && sleep 1 && sudo mount /dev/mapper/loop0p1 /home/data/stretch/loop0p1 && sleep 1 && sudo mount /dev/mapper/loop0p2 /home/data/stretch/loop0p2 && loop_info.py


rifle.confの最初の方に記載しておきます。
rangerからはloop0の決め打ちにしているのでloop0デバイスだけがマウント可能になります。

loop_info.pyの作成

python(tkinter)を利用してメッセージボックスを作成します。
~/bin/loop_info.py

#!/usr/bin/python3
import subprocess
from tkinter import messagebox

command = ("df -h | grep loop | cut -c 1-20 && ls /dev/mapper")
proc = (subprocess.Popen(command, stdout=subprocess.PIPE, shell=True).communicate()[0]).decode('utf-8')
messagebox.showinfo('loop_info', proc)
$ chmod 755 ~/bin/loop_info.py

上記rangerのrifle.confに追記した最後にloop_info.pyの起動を記載しています。
参考 [備忘録]Pythonでシェルコマンドを動かす
コマンドからの出力(取得)はバイト文字列になっているようです。decodeで日本語表示も可能です。
rangerを再起動して2018-11-13-stretch-pi3.imgを選択

マウントが成功すると画像のようにメッセージを表示します。
loop0p1にboot、loop0p2にrootfsがそれぞれマウントされます。


マウントしたファイルはOSのイメージそのものなのでOSを壊さない範囲で自由に編集可能ですがraspbianは適当な時期で変更になるため特に事情が無い限りあまり凝った編集をしても意味がありません。WiFi接続情報やインストール後の作業が楽になるような設定を加えるのがいいと思います。

loop_remove.pyの作成

loop deviceのアンマウント、片付けは前回作成したランチャを使用します。
シェルコマンドの実行はos.systemからsubprocessに(推奨)代わっているようですね。
python3.5以降から使えます。
~/bin/loop_dev.py

#!/usr/bin/python3

from tkinter import *
from tkinter import ttk 
import subprocess

root = Tk()
root.title('loop_device')
style = ttk.Style()
style.theme_use('default') #('clam', 'alt', 'default', 'classic')

# Frame as Widget Container
frame1 = ttk.Frame(
    root,
    padding=5)
frame1.grid()

# Button 1
def remove0():
    subprocess.run("sudo umount /home/data/stretch/loop0p1", shell=True)
    subprocess.run("sudo umount /home/data/stretch/loop0p2", shell=True)
    subprocess.run("sudo dmsetup remove loop0p1", shell=True)
    subprocess.run("sudo dmsetup remove loop0p2", shell=True)
    subprocess.run("sudo losetup -d /dev/loop0", shell=True)
    subprocess.run("loop_info.py")
icon1 = PhotoImage(file='~/.icons/folder-loop.png')
button1 = ttk.Button(
    frame1,
    image=icon1,
    command=remove0)
button1.grid(row=1,column=1)

# Button 2
def loop_dev():
    subprocess.run("loop_info.py")
icon2 = PhotoImage(file='~/.icons/text-info.png')
button2 = ttk.Button(
    frame1,
    image=icon2,
    command=loop_dev)
button2.grid(row=1,column=2)

# Button 3
def shutdown():
    subprocess.run("sudo reboot", shell=True)
icon3 = PhotoImage(file='~/.icons/reboot100x48.png')
button3 = ttk.Button(
    frame1,
    image=icon3,
    command=shutdown)
button3.grid(row=2,column=1)

# Button 4
def cancel():
    root.quit()
icon4 = PhotoImage(file='~/.icons/exit100x48.png')
button4 = ttk.Button(
    frame1,
    image=icon4,
    command=cancel)
button4.grid(row=2,column=2)

root.mainloop()
$ chmod 755 ~/bin/loop_remove.py

loop_remove.pyを実行します。

infoボタンで現在の状態を確認できます。
左はrebootボタン
exitボタンはなにもしないで終了します。


loop0ボタンでアンマウント、loop0デバイスの解除を実行します。
rangerなどからloop0デバイスへアクセスがあるとアンマウントに失敗するのでディレクトリから離れておきます。
成功するとcontrolのみを表示します。


現状のプログラムではloop0マウント後にほかのimgを実行するとloop1が作成されてしまいます。削除するにはコマンドラインから外すかまたはrebootを実行します。


次回はこの編集したimgを使用してPi3のディスクを作成、インストールしてみたいと思います。