注目キーワード

【Jetson Nano】自分の記憶が信じられない貴方へ。。(セットアップ自動化)

すけろく
なに!いつのまに入った!?
曲者じゃ~
げんろく
何事かえ?
曲者なんぞ、どこにもおらんぞ。
今度はなにがあったのだ?
すけろく
いつの間にか、知らぬパッケージが入っておるのだ!
曲者がこっそりやったに違いない!
げんろく
どれどれ。昨日、このパッケージを入れてなかったか?
知らぬというパッケージは「依存パッケージ」に含まれておるぞ。
すけろく
わしが、わしが、やったのか・・・
この手で~(泣)

 

さて、皆さんは、Ubuntuのパッケージをどのように管理されていますか?

Ubuntuにパッケージを導入する際には、「apt」やpythonであれば「pip」,「pip3」を使いますが、その際に管理が難しいのが「依存パッケージ」ですよね。

新しいパッケージを入れた際に、過去に入れたパッケージが依存パッケージであると、意識しないうちに更新されている・・・なんてことも多いのではないでしょうか。

確認すれども・・ちょっと足りない

確認方法としては、「apt」や「dpkg」コマンドを使えば、実行時点のパッケージ環境のリスト化、パッケージのビルド情報の確認ができ、いつ頃更新されたかを推測することができます。

でも「いつ、どのようなコマンドで、何を入れたときに、更新されたか」というのは可視化しにくいです。

特に開発時点でちょこちょこパッケージ環境を更新していくと、いざ、本番環境にその環境を作る際に手番が抜けて時間をロスする可能性が高まります。

そこで、今回は、Ubuntu のパッケージインストールの自動化と、環境更新の可視化を行うツールを作成しました。

とりあえず、Jetson NanoのUbuntu OS用に絞って作ってみましたのでご参考になればと思います。

 

このプログラム(ツール)の動作対象となるJetson Nanoについて、最低限必要な購入品を以下の記事でご紹介しています。
参考にしてくださいね!

Jetson Nano Developer Kitを始めるためのお買い物リストをまとめました!ぜひご覧ください。

関連記事

こんな悩みありませんか? 「Jetson Nano はじめたいけど、何があれば遊べるの? いくらかかるの?」 そんなご質問に答えるべく、購入品リストをまとめてみました。 本記事は以下の記事「【Jetson Nano】まずや[…]

 

【合わせて読みたい】、Jetson Nanoをご利用の方向けの人気記事も、ぜひご覧ください!
関連記事

すけろく Raspberry PiやJetsonのシングルボードコンピュータを使っていると 必要になるmicroSDカード。 何を買えばよいのやら。。。 げんろく microSDカードには意外といろ[…]

 

どのようなツールがいいかな

名付けて「JetRunStep」です。
まあ、ステップ実行していく的なノリで名付けました。

ツールは以下の2つの機能を持っているといいですね。

  • json形式ファイルに記載したシェルコマンドの実行内容を順次実行していく(自動化)
  • シェルコマンド実行毎(もしくはjson形式ファイル毎)に履歴を残す(可視化)

可視化は、できる限りシンプルなイメージにしました。次のようなHTMLファイルを生成します。
イメージは、「pip3」のインストールコマンド「sudo apt install python3-pip」を実行した結果、新たに導入されたパッケージを表示しているところです。
(Show/Hideのアイコンを押すことで履歴が表示されます)

 

ツールを作るにあたり、考慮した条件は次の通りです。

  • Jetson Nanoで提供されているOS Imageの初期段階から使用できること
  • データベースなどツール実行のためのパッケージインストールが必要ないこと
  • 可視化は:パッケージ名、バージョン、更新日、更新時のコマンドについて残すこと

今回は各機能の実装にあたり、次のライブラリを使用しています。

機能 使用した主なPythonライブラリ
自動化 基本制御(os, sys, shutil)、日時取得(datetime)、ログ生成(logger)、
実行オプション制御(argparse)、
サブプロセス実行(subprocess)
jsonファイル読込(json)
可視化 XMLパーサー(ElementTree)
XML成型(minidom)

更新履歴の構造化保存をどうするか悩んだ末、XMLにしました。
パーサーでの検索処理に時間はかかりますが、データベースなどは使用せず、単一のXMLファイルにて構造化して管理可能であるため、XMLを選定しました。

 

XMLパーサーを使う

今回のツールの肝は、やはりXMLパーサーです。

Pythonには「ElementTree」というXML用のライブラリが用意されています。

このライブラリを使用することで次の処理を実装できます。

  • XML構造の生成
  • XML構造のファイルや文字列からの読み込み
  • XML構造内の要素の検索
  • XML要素値や属性値の編集

以下のページにリファレンスマニュアルはありますが、ちょっと読んでいて混乱したので、今回使う内容について解説します。

ElementTreeのマニュアルはこちら

XML構造の生成

XML構造を生成する場合は以下のようにします。

[生成結果 例]

<?xml version="1.0" ?>
<Pkglist>
<!-- Generated for JetRunSetup by GENROKU@Karakuri-Musha -->
    <Package flg="1" name="accountsservice">
        <Trace  order="0">
            <Versions>0.6.45-1ubuntu1.3</Versions>
            <Updatedate>2021.09.30</Updatedate>
        </Trace>
    </Package>
</Pkglist>

[Pythonプログラム記述例]

from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement, Comment
# ①XMLファイルのヘッダ作成
xml_root = Element(”Pkglist”)
# ②XMLへのコメント付与
comment = Comment('Generated for JetRunSetup by GENROKU@Karakuri-Musha')
xml_root.append(comment)
# ③XMLに要素や属性値などを追加する
xml_pkg = SubElement(xml_root, "Package")         # ルートに子要素「Packageを追加」
xml_pkg.set("name", "accountsservice")               # 要素「Package」に属性「name」を追加
xml_pkg.set("flg", "1")                                              # 要素「Package」に属性「flg」を追加 
xml_item = SubElement(xml_pkg, "Trace")             # 要素「Package」に子要素「Trace」を追加
xml_item.set("order", "0")            # 要素「Trace」に属性「order」を追加 
xml_ver = SubElement(xml_item, "Versions")        # 要素「Trace」に子要素「Versions」を追加
xml_ver.text =”0.6.45-1ubuntu1.3# 要素「Versions」に値を追加
xml_date = SubElement(xml_item, "Updatedate") # 要素「Trace」に子要素「Updatedate」を追加
xml_date.text = f"{datetime.now():%Y.%m.%d}"   # 要素「Updatedate」に値を追加
# ④XML構造をファイルに出力する
p_elemtree = ElementTree.ElementTree()               # ElementTreeを生成
p_elemtree._setroot(xml_root)                                  # 先ほど要素を追加したXML構造のルートを設定
p_elemtree.write(i_xml_file_d, encoding="utf-8", xml_declaration=None, method="xml")     # ファイルへ書き出し

 

XML構造のファイルや文字列からの読み込み

既にあるXMLファイル「例:Env_trace.xml」を読み込む場合は次のようになります。

[Pythonプログラム記述例]

xml_tree = ElementTree.parse("Env_trace.xml")

 

XML構造内の要素の検索

XML構造内の特定の要素にアクセスする場合は、次のように検索して結果を取得します。
ElementTreeは、XPathの記述方法が使えます

[検索するXML構造 例]

<?xml version="1.0" ?>
<Pkglist>
<!-- Generated for JetRunSetup by GENROKU@Karakuri-Musha -->
    <Package flg="1" name="accountsservice">
        <Trace  order="0"> 
            <Versions>0.6.45-1ubuntu1.3</Versions> 
            <Updatedate>2021.09.30</Updatedate> 
        </Trace> 
    </Package> 
    <Package flg="1" name="aci">
        <Trace  order="0"> 
            <Versions>2.2.52-3build1</Versions> 
            <Updatedate>2021.09.30</Updatedate> 
        </Trace> 
    </Package> 
</Pkglist>

[Pythonプログラム記述例]

XML構造から「accountsservice」を属性値に持つ要素の「Versions」要素を検索して値を取得します。
※XML構造の検索結果は複数になる場合があるので注意が必要です。

q_str = "./Package[@\'name\'=\'accountsservice\']//Versions"
p_versions = xml_tree.findall(q_str).text

検索文字列の中で「Versions」の前に「//」となるのは、「Package」要素直下だけでなく孫要素も検索させるためです。

 

XML構造内の要素値や属性値の編集

前述の検索結果で得られた結果に対して要素値を変更してみます。

q_str = "./Package[@\'name\'=\'accountsservice\']//Versions" 
for elem in xml_tree.findall(q_str):
    elem.text = "Sample version"          # 要素値の編集
    elem.set("flg", "1")                           # 属性値の編集

 

いかがでしょうか。初めてマニュアルを読んだ際には、ElementとElementTreeの扱い方に戸惑いました。
実際に使われる際には、いろいろ試していただければと思います。

自動セットアップ&パッケージ更新履歴管理ツールをつくる

それではPythonを使ってプログラムを作ってみましょう。

先ほど考えた仕組みを含め、以下のようにプログラミングします。

  • ツールは、コマンド単体と複数コマンド(json形式ファイル)の2種類の実行方法とする
  • パッケージバージョンの確認は、全コマンド毎(All)またはツール実行毎(Once)の2種類とする
  • 管理用のXMLファイルは可読性は考えない。(インデントなどをつけない)
  • ツール実行時にオプションで参照用XMLファイル名を付けた場合、可読性の高いフォーマットで出力する
  • 標準でHTML形式での出力を行う。
  • HTMLのデザイン、アコーディオン表示などはCSS、JavaScriptで実装する。
    (後でデザインなどの変更が個別に行えるようツール出力ファイルとは別に作る)

わかりやすく、図で表すと次のようなイメージです。

 

自動セットアップ&パッケージ更新履歴管理ツール

ツールのプログラム構成は次のように作成しました。

Pythonスクリプト名
:JetRunStep.py
ツール動作設定ファイル
:JetRunStepSetting.json
プログラム実行想定環境
OSバージョン
Jetson Nano Developer Kit OS Image
(Ubuntu 18.04.5 LTS)
動作確認機器
Jetson Nano Developer Kit(B01:4GB)
Pythonバージョン
Python 3.6.9
ライセンス
MIT License

 

ツールは次のファイル/ディレクトリ構造にしています。
※pyinstaller などを使用した実行ファイル化も考えましたが、ファイル容量と、処理内容の可視化のため次の構成にしました。

 

プログラムはGitHubにて公開していますのでぜひ使ってくださいね!

 

 GitHub公開情報

プログラムはGitHubにて公開しています。以下からご利用ください!

GitHub

Contribute to karakuri-musha/JetRunStep development by creat…

 

 利用方法

[1] インストールと実行方法(How to install and run)

1.ツール配置用のディレクトリに移動します。

cd <Tool Save Directory>

2.ディレクトリにツールをコピーします。コピー後ツールディレクトリに移動します。
移動後に一度ツールを実行してください。管理用XMLが作成されます。

sudo git clone https://github.com/karakuri-musha/JetRunStep.git
cd JetRunStep
pyhon3 JetRunStep.py -i 'ls -l'

3-1.シェルコマンドを単体で実行する場合
(例:Python3-pipをインストールする場合は以下のコマンドになります。)
※参照用XMLファイルを作る場合は例えば、「 -v Env_brows.xml 」を追加します。

pyhon3 JetRunStep.py -i 'sudo apt install python3-pip'

3-2.jsonファイルにシェルコマンドを複数記載して順次、自動実行させる場合
(例:Jetson_to_do_001.jsonをコマンドファイルとして使用する場合は以下のコマンドになります。)
※参照用XMLファイルを作る場合は例えば、「 -v Env_brows.xml 」を追加します。

pyhon3 JetRunStep.py -a Jetson_to_do_001.json

※Jetson_to_do_001.jsonファイルの記載方法は、次の章で記載します。

4.ツール実行結果として、ツール実行ディレクトリに「Log」ディレクトリが作成されます。
フォルダ内に実行時のログが保存されることを確認してください。

【ログ内容:例 初回実行時】

2021-10-01 11:45:14,137@ Common.kmg_common [INFO] check_system_env: System Enviroment Check Process Begin
2021-10-01 11:45:14,148@ Common.kmg_common [INFO] check_system_env: The operating system is [Linux]
2021-10-01 11:45:14,154@ Common.kmg_common [INFO] check_system_env: The model name is [NVIDIA Jetson Nano Developer Kit]
2021-10-01 11:45:14,160@ Common.kmg_common [INFO] <module>: delete log file : ./Log/log20211001110047.log
2021-10-01 11:45:14,161@ Common.kmg_common [INFO] <module>: Start the Jetson Nano Run Setup Tool (JetRunStep) .
2021-10-01 11:45:14,169@ Common.kmg_common [INFO] run_one_cmd: total 584

-- シェルコマンド実行時のPIPEの情報が記載される --

2021-10-01 11:43:49,795@ Common.kmg_common [INFO] create_xml: The environment configuration check (init) will start.
2021-10-01 11:43:50,062@ Common.kmg_common [INFO] create_xml: The environment configuration check (init) is complete.
2021-10-01 11:43:50,065@ Common.kmg_common [INFO] run_one_cmd: Since this tool was executed for the first time, an administrative file (Env_trace.xml) was created.
2021-10-01 11:45:30,093@ Common.kmg_common [INFO] create_xml_view: Start generating XML file for reference.
2021-10-01 11:45:31,288@ Common.kmg_common [INFO] update_file_full: ---- Update file ----
2021-10-01 11:45:31,290@ Common.kmg_common [INFO] update_file_full: ---- Success Update file ----
2021-10-01 11:45:31,291@ Common.kmg_common [INFO] create_xml_view: Complete generating XML file for reference.
2021-10-01 11:45:31,294@ Common.kmg_common [INFO] create_html: Start HTML file generation.
2021-10-01 11:45:31,359@ Common.kmg_common [INFO] create_html: End HTML file generation.
2021-10-01 11:45:31,365@ Common.kmg_common [INFO] update_file_full: ---- Update file ----
2021-10-01 11:45:31,368@ Common.kmg_common [INFO] update_file_full: ---- Success Update file ----

【ログ内容:例 2回目以降】

2021-10-01 11:45:14,137@ Common.kmg_common [INFO] check_system_env: System Enviroment Check Process Begin
2021-10-01 11:45:14,148@ Common.kmg_common [INFO] check_system_env: The operating system is [Linux]
2021-10-01 11:45:14,154@ Common.kmg_common [INFO] check_system_env: The model name is [NVIDIA Jetson Nano Developer Kit]
2021-10-01 11:45:14,160@ Common.kmg_common [INFO] <module>: delete log file : ./Log/log20211001110047.log
2021-10-01 11:45:14,161@ Common.kmg_common [INFO] <module>: Start the Jetson Nano Run Setup Tool (JetRunStep) .
2021-10-01 11:45:14,169@ Common.kmg_common [INFO] run_one_cmd: total 584

-- シェルコマンド実行時のPIPEの情報が記載される --

2021-10-01 11:45:14,289@ Common.kmg_common [INFO] update_xml: The environment configuration check will start.
2021-10-01 11:45:30,090@ Common.kmg_common [INFO] update_xml: The environment configuration check is complete.
2021-10-01 11:45:30,093@ Common.kmg_common [INFO] create_xml_view: Start generating XML file for reference.
2021-10-01 11:45:31,288@ Common.kmg_common [INFO] update_file_full: ---- Update file ----
2021-10-01 11:45:31,290@ Common.kmg_common [INFO] update_file_full: ---- Success Update file ----
2021-10-01 11:45:31,291@ Common.kmg_common [INFO] create_xml_view: Complete generating XML file for reference.
2021-10-01 11:45:31,294@ Common.kmg_common [INFO] create_html: Start HTML file generation.
2021-10-01 11:45:31,359@ Common.kmg_common [INFO] create_html: End HTML file generation.
2021-10-01 11:45:31,365@ Common.kmg_common [INFO] update_file_full: ---- Update file ----
2021-10-01 11:45:31,368@ Common.kmg_common [INFO] update_file_full: ---- Success Update file ----

 

[2] コマンド収録ファイルの編集方法(How to edit the shell command file (.json))

複数のシェルコマンドを収録したファイルを作成するためには、ツールに添付の「Jetson_to_do_001.json」を編集します。ファイル内の記載方法は次の通りです。


パターン1. シェルコマンドを実行する場合の記述

{"type":"cmd", "comment":"Execution [pip3 install]", "cmd":"sudo apt install python3-pip"}
  • type : “cmd” (実行形式をコマンド「cmd」に設定します。)
  • comment : “Execution [pip3 install]” (ツール実行時ログへの表示名を指定します。)
  • cmd : “sudo apt install python3-pip” (実行するシェルコマンドを指定します。(例は「pip3」のインストール用コマンド)

パターン2. 指定したファイルの任意の行を置き換える場合

{"type":"frc", "comment":"Execution [Update boot file]", "cmd":"/boot/config.txt", "original":"#dtparam=i2c_arm=on", "after":"dtparam=i2c_arm=on\nstart_x=1\n"}
  • type : “frc” (実行形式をコマンド「frc」に設定します。)
  • comment : “Execution [Update boot file]” (ツール実行時ログへの表示名を指定します。)
  • cmd : “cmd”:”/boot/config.txt” (編集するファイルの絶対パスを記載します。)
  • original : “#dtparam=i2c_arm=on” (置き換える元の行の文字列を記載します。)
  • after : “dtparam=i2c_arm=on\nstart_x=1\n” (置き換え後の行の文字列を記載します。)

パターン3. 指定したファイルの先頭行に任意の行を挿入する場合

{"type":"ffc", "comment":"Execution [Update test file]", "cmd":"/boot/config.txt", "original":"", "after":"Insert first Line"}
  • type : “ffc” (実行形式をコマンド「ffc」に設定します。)
  • comment : “Execution [Update test file]” (ツール実行時ログへの表示名を指定します。)
  • cmd : “cmd”:”/boot/config.txt” (編集するファイルの絶対パスを記載します。)
  • original : “” (使用しません。)
  • after : “Insert first Line” (先頭行に挿入する文字列を記載します。)

パターン4. 指定したファイルの最終行に任意の行を追記する場合

{"type":"fec", "comment":"Execution [Update test file]", "cmd":"/boot/config.txt", "original":"", "after":"Insert End Line"}
  • type : “fec” (実行形式をコマンド「fec」に設定します。)
  • comment : “Execution [Update test file]” (ツール実行時ログへの表示名を指定します。)
  • cmd : “cmd”:”/boot/config.txt” (編集するファイルの絶対パスを記載します。)
  • original : “” (使用しません。)
  • after : “Insert End Line” (最終行に追記する文字列を記載します。)

 

編集後記

いかがだったでしょうか。

今回のツールはXMLを扱うプログラムとして作成してみました。

さすがにXML構造を検索しながら更新する処理の部分は重くなりました。

「pip3」をインストールした際の更新内容をHTMLファイルで見てみると、思っていたよりも多くパッケージが入っていることがわかります。

今後、作成するプログラムの実行環境をご紹介する際に、このツールを使ってセットアップできるようになればなと考えています!

皆さんのお役に立てれば幸いです。

長い記事でしたが、最後までご覧いただきありがとうございました!

 こちらの記事もあわせてどうぞ!!

Jetson Nanoは、Raspberry Piと同様に最低限のキットしか本体には付属していないため、追加購入が必要になってきます。特に通信モジュールの購入は注意が必要です。

最低限必要な購入品については、以下の記事でご紹介しています。参考にしてくださいね!

Jetson Nano Developer Kitを始めるためのお買い物リストをまとめました!ぜひご覧ください。

関連記事

こんな悩みありませんか? 「Jetson Nano はじめたいけど、何があれば遊べるの? いくらかかるの?」 そんなご質問に答えるべく、購入品リストをまとめてみました。 本記事は以下の記事「【Jetson Nano】まずや[…]

 

【合わせて読みたい】、Jetson Nanoをご利用の方向けの人気記事も、ぜひご覧ください!
関連記事

すけろく Raspberry PiやJetsonのシングルボードコンピュータを使っていると 必要になるmicroSDカード。 何を買えばよいのやら。。。 げんろく microSDカードには意外といろ[…]