MimixBoxはGolang学習用アプリとして開始 

Golang製のMimixBoxは、BusyBox(多数のUnixコマンドをシングルバイナリに詰め込んだCLIアプリ)と共通点を持ちつつ、独自の目標を持つCLIアプリとして開発しています。

開発のキッカケは、Golangを学習するためです。前職を退職して、新しい会社では開発経験のないGolangがメイン言語となりました。即戦力となれるよう、私は勉強のためにCLIツールや独自シェルを作り始めましたが、「全部混ぜて開発すればプロジェクト数が増えず、管理が楽では?それなら、BusyBoxを真似するか」という考えに至りました。

ここまで来れば「MimixBox - Mimic BusyBox on Linux(Linux上でBusyBoxを模倣する)」という名称を考えつくのは、一瞬でした。ちなみに、同様のプロジェクトにはtoyboxgoboxがあります(皆、考える事は大体一緒)。

MimixBoxはBusyBoxと違う道を目指す

MimixBoxは、Linux****デスクトップ環境でのCLI(Terminal操作)が楽しくなる事を目指します!そのため、「既存Unixコマンドの機能拡張(例:catに対するbat、lsに対するlsd)」や「独自コマンドの組み込み」が大事だと考えています。

上記のように考えた理由は「大きめなバイナリサイズ」と「対応コマンド数でBusyBoxに追いつけない事」です。

C言語製のBuxyBoxは、制約の多い組み込み環境でも動作する事から分かるように、バイナリサイズがかなり小さめです。私の環境では、コマンド263個を組み込んだBusyBoxのサイズは約2MBでした。

その一方で、コマンドを数個しか組み込んでいないMimixBoxは、サイズが約4MBありました(現在はコマンド42個で約5.6MB)。デバッグシンボルなどの不要な情報をstripしてもBusyBoxの2倍を超えるサイズなので、MimixBoxは組み込み環境向けとするのは無謀でした。

また、BusyBoxはコマンド数が400個以上あり、ドマイナーOSSのMimixBoxが同路線(量を増やす事)を真似しても勝ち目がありません。MimixBoxの出自はBusyBoxの模倣品ですが、BusyBoxを100%模倣しても面白くないので「じゃあ、コマンド単位の質を上げるか」と発想しました。

MimixBoxのロードマップ

MimixBoxはGolang学習用のOSSという側面もあるので、全て独自コマンドで構成するような事はしていません。まずは、一般的なUnixコマンドを量産しつつ、合間に独自コマンドを開発するようなスタイルで進めています。

〜2022年12月:MimixBoxロードマップ

  • Step1. 100件以上のUnixコマンドを実装(機能の増加、〜Version 0.XX.xx)
  • Step2. オプションおよびテストを拡充(品質向上、〜Version 1.XX.xx)
  • Step3. コマンドを近代的な仕様に変更(独自性の追加、〜Version 2.XX.xx)

MimixBoxの独自オプション

MimixBoxは、BusyBoxとはオプションが異なります。下表にオプション一覧を示します。

(◯はMimixBox独自、△はBusyBoxから仕様変更、×はBusyBoxと同じ挙動)

オプション独自(仕様変更)仕様
-i, –installMimixBox組み込みコマンドのシンボリックリンクを指定ディレクトリに作成する。ただし、システムに同名コマンドが存在する場合は、リンク作成しない。
-f, –full-installMimixBox組み込みコマンドのシンボリックリンクを指定ディレクトリに作成する
-h, –help×ヘルプメッセージを表示する
-l, –listMimixBox組み込みコマンド名称と説明文を表示する
-r, –removeMimixBox組み込みコマンドのシンボリックリンクを削除する
-v, –version×バージョン情報を表示する

オプションに独自性を出した理由は、「MimixBox開発中にシステムをブッ壊したから」です。引数処理を間違えた結果、MimixBoxの提供するcatコマンドが動きませんでした。運悪くGUIライブラリがcatコマンドを使っていたので、GUI起動が必ず失敗するようになりました。

この問題の対策として、「–installオプションが安全インストール(システムに存在しないコマンドのみシンボリックリンク作成)」「–full-installオプションがBusyBoxと同仕様」としました。さらに、レスキューモードでのシステム復旧が簡便になるように、–removeオプションでシンボリックリンクを一掃できるようにしました。

現在は、Docker内でMimixBoxをテスト可能な状態にしたので、より安全に遊べます。

MimixBox開発中の気づき(感想)

気づき(感想)は、3つあります。その内容は、「プロジェクトの感触が良い事」「Golangと親友に慣れない事」「ユニットテストの重要性」についてです。

MimixBoxプロジェクト(2021年11月28日現在での規模は約5000[LOC])は、開発開始して1ヶ月弱。Golangの文法やAPIを着実に学べており、個人的には良いプロジェクトと感じています。長期間付き合って行けそうなプロジェクトである点も好ましく、「便利なOSSになると良いなー」と考えながら実装してます。

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Go                              56           1142           1136           4999
Markdown                        25            299              0           1186
Bourne Shell                     5             47             42            252
make                             1             10              0             32
Dockerfile                       1              5              5              7
-------------------------------------------------------------------------------
SUM:                            88           1503           1183           6476
-------------------------------------------------------------------------------

Golangと親友になれない件は、身も蓋もない話ですが、私はGolangがあまり好きではなく。個人的な印象では「Golangは便利なC言語」止まりであり、どちらかと言えば私はクラス指向の強いJavaやRubyの方が好み。C言語やGolangを書いている時はデータ中心に設計できなくなる傾向(癖)があり、処理をシーケンシャルに記述しがち。まだ慣れていないという事でしょうか。

ユニットテストの重要性については、言うまでもないでしょう。今回は、Version1.0.0(= コマンドを100件程度作成した状態)でユニットテストを量産する予定でした。しかし、MimixBox組み込みコマンド全体に影響がある修正が必要になった時、「テストを先に作れば良かった……」と後悔しました。

全コマンドに影響がある修正は、何度も発生しました。例えば、「パイプ("|")対応」「リダイレクト(">“や”»")対応」「引数で指定された環境変数の展開」あたりは、初期実装時には未対応でした。そのため、途中で機能追加しました。が、テストが無かったのでデグレしているのかが即座に分からず、手間が多くかかりました。

同じ轍を踏まないように、Version 1.0.0に移行する前にユニットテストを作り始めようかな、と考えている次第です。

Pull Requestを歓迎します

MimixBoxは、2021年11月28日現在で42個のコマンドをサポートしています(一部、基本機能すら未完成コマンドがありますが……)。より多くのコマンドをサポートしたいので、「未サポートコマンド(独自コマンド含む)の追加」「オプション追加」「バグ修正」など、PRいただけると大変嬉しいです。

以下、MimixBoxに組み込んでいるコマンド(サポートコマンド)リストです。

nao@nao:~/.go/src/github.com/nao1215/mimixbox$ ./mimixbox --list
   base64 - Base64 encode/decode from FILR(or STDIN) to STDOUT
 basename - Print basename (PATH without"/") from file path
      cat - Concatenate files and print on the standard output
   chroot - Run command or interactive shell with special root directory
   cowsay - Print message with cow's ASCII art
       cp - Copy file(s) otr Directory(s)
 dos2unix - Change CRLF to LF
     echo - Display a line of text
   expand - Convert TAB to N space (default:N=8)
fakemovie - Adds a video playback button to the image
    false - Do nothing. Return unsuccess(1)
    ghrdc - GitHub Relase Download Counter
   groups - Print the groups to which USERNAME belongs
     head - Print the first NUMBER(default=10) lines
   hostid - Print hostid (Host Identity Number, hex)!!!Does not work properly!!!
       id - Print User ID and Group ID
 ischroot - Detect if running in a chroot
       ln - Create hard or symbolic link
     mbsh - Mimix Box Shell
   md5sum - Calculate or Check md5sum message digest
    mkdir - Make directories
   mkfifo - Make FIFO (named pipe)
       mv - Rename SOURCE to DESTINATION, or move SOURCE(s) to DIRECTORY
       nl - Write each FILE to standard output with line numbers added
     path - Manipulate filename path
       rm - Remove file(s) or directory(s)
    rmdir - Remove directory
      seq - Print a column of numbers
   serial - Rename the file to the name with a serial number
  sha1sum - alculate or Check sercure hash 1 algorithm
sha256sum - alculate or Check sercure hash 256 algorithm
sha512sum - alculate or Check sercure hash 512 algorithm
       sl - Cure your bad habit of mistyping
    sleep - Pause for NUMBER seconds(minutes, hours, days)
      tac - Print the file contents from the end to the beginning
     tail - Print the last NUMBER(default=10) lines
    touch - Update the access and modification times of each FILE to the current time
     true - Do nothing. Return success(0)
 unexpand - Convert N space to TAB(default:N=8)
 unix2dos - Change LF to CRLF
    which - Returns the file path which would be executed in the current environment
   whoami - Print login user name

コントリビュートに関する資料(コマンド追加方法含む)は、コチラに記載しています。基本的なルールは、「GPLv2ライセンスのコードは含めないでください」と「テストコードなくてもOK」ぐらいしかありません。

また、MimixBoxの開発状況を伝えるためのTwitterアカウントがあります(ちょっと作るの早いと思いましたが……)。日本語と英語の両方で情報発信して行く予定ですので、ご興味があればフォローお願いいたします!

GitHub Sponsorsでスポンサーを募集中

最近話題のGitHub Sponsorsに対応しています!

金銭的な支援をいただけるのは単純に嬉しいですし、誰かにサポートしていただいている事実はそれだけでモチベーションが上がります。以下のボタンを押してもスポンサーページに飛ぶだけなので、安心してクリックしてみてください。

スポンサーの方へのお礼(金額によって対応可否が異なります)

  • MimixBoxのコントリビュータリスト(支援者一覧)に名前を記載
  • Twitter上でのお礼(名前およびSNSアカウントを併記)
  • 優先的に開発するコマンドの決定権(コマンド1個分かつ規模200〜500[LOC]程度)

 おまけ:2022年に作成したGolang製コマンド一覧