Scratchは子供の教育用に開発されたプログラミング言語です。Raspberry Piで動いたり、NHKの教育番組で取り上げられたりと、いろいろな場所で活躍しています。今回はそのScratchの最新版である2.0をUbuntuで使う方法を紹介します。
Scratch 1.4とScratch 2.0
「Scratch 」はMITメディアラボが開発したプログラミング言語です。子供が学習することを主眼に置いているため、他のプログラミング言語に比べると学びやすく、視覚的な効果が多彩な作りになっています。
たとえば先日NHK教育で放送された「Why!? プログラミング 」では、プログラミング番組の教材としてScratchを使っています[1] 。教育用コンピューターとして始まったRaspberry PiのOSにもScratchが最初からインストールされています。また、Scratchのサイトには言語の紹介だけでなく、「 保護者の方へ 」や「教育関係者の方へ 」といったコンテンツがあることも特徴です。
さて、Scratchにはバージョンとして「1.4」と「2.0」が存在します。Scratch 1.4はスタンドアローンなアプリケーションで、Ubuntuでも以前からパッケージ管理システム経由でインストールできます。それに対してScratch 2.0 はウェブアプリケーションになりました。つまりインターネットにつながっているウェブブラウザ(とAdobe Flash)があれば、どんなマシン上でもプログラミングできるということです。
Scratch 2.0ではウェブ上での共有機能も充実し、ウェブサイトにも簡単に作成したプロジェクトを埋め込めるようになりました。現在では、日本はもちろんのこと世界中で活発な開発コミュニティが形成されているようです。前述のNHK教育の番組でも、番組内で作成したプロジェクトは番組のサイトで公開されています 。また、プロジェクト自体はScratchのサーバー上にあるため、誰でも番組で使ったコードを読めるのです。
ところでScratch 2.0がウェブアプリケーションであるということは、インターネットにつながっていないと実行はおろかプログラミングもできないということです。インターネットへの接続環境が充実している日本だとそこまで問題にはなりませんが、世界に目を向ければオフラインでScratch 2.0を使いたいという要望はまだまだあるはずです。
そこでScratch 2.0には「オフラインエディター 」というインターネットに接続せずともプログラミングできるソフトウェアがあります。今回はこれを使うことにしましょう[2] 。オフラインエディターはWindowsやMac OS XだけでなくLinuxもサポートしており、動かすためにはAdobe AIR が必要なんだそうです。
[2] プログラミングするだけならScratch 1.4 を使うというのも手です。何よりRaspberry Piではアーキテクチャの都合でScratch 1.4しか使えません。Scratch 2.0で作られたプロジェクトを動かすことはできませんが、1.4で作ったプロジェクトをScratchのサイトにアップロードしたり公開することは可能です。
図1 無情にも踊る「Linux 版 Adobe AIR のサポートは終了しました」の文字列
……あー、Adobe AIRですかー。あー。
Scratch 2.0をコンテナにインストールする
Adobe AIRは32bitバイナリしか提供していません。つまり64bit環境で実行しようとすると、32bitライブラリをまず用意しなくてはいけないのです。そもそもサポートの切れた、しかもソースコードが公開されていないバイナリをシステムにインストールすることに抵抗がある方も多いことでしょう。
そこで今回はLXDコンテナの中に32bit版のUbuntu環境を用意し、そこにAdobe AIRやScratch 2.0をインストールすることにします。
LXDのインストール
「LXD 」は「コンテナのハイパーバイザー」として開発されているサービスです。簡単に言うと、複数のホストにまたがった複数のLXC製のコンテナをより簡単に管理できるツールです。コンテナの起動や終了は元より、スナップショットの作成、ライブマイグレーション、稼働中のコンテナからのベースイメージの作成、イメージの公開、複数のコンテナに適用できるプロファイルなどなど、これまでLXCの複数のコマンドと設定ファイルを駆使していた作業が、一つのコマンドから操作できるようになっています[3] 。
LXDは現在、Ubuntu 16.04 LTSにあわせて2.0をリリースすべく、リリース候補版が提供されています。サーバー版の16.04では、このLXD 2.0が最初からインストールされる予定ですので、今回はLXD 2.0を使うことにします。( 本稿掲載時ではまだ開発中の)16.04を使っている場合は、次のようにインストールしてください。
$ sudo apt install lxd
ちなみに、LXD 2.0は14.04にもバックポートされています。よって、14.04でも次のようにインストールできます。
$ sudo apt -t trusty-backports install lxd
またインストール後に「sudo lxd init」を実行すると、ZFSなどの設定を行えます。必要な場合は設定してください。
ここまで完了したら、lxdグループに参加するために一度ログインしなおしてください。ログインしなおしても参加していないようなら手動で参加させておきましょう。LXDの本体はデーモンとして動作しています。lxdグループに所属しているユーザーはこのデーモンとunixドメインソケットで通信できます。よって以降の作業は、sudoが不要です。
Ubuntuコンテナの作成
Ubuntu 16.04 LTSの32bit(i386)版のコンテナを「scratch」という名前で用意します。16.04にしているのは単にこの先よく使うであろうからというだけで、14.04でもかまいません。また、アーキテクチャがamd64であるシステムでも、i386やarmhfのコンテナを動かすことができます。よって、ここから先の手順はホストのOSやアーキテクチャに関係なく同じ手順となります。
$ lxc launch ubuntu:16.04/i386 scratch
$ lxc exec scratch apt update
$ lxc exec scratch apt full-upgrade
$ lxc exec scratch apt install language-pack-ja
$ lxc exec scratch update-locale LANG=ja_JP.UTF-8
launchサブコマンドは必要であればLXDイメージをダウンロードし、指定した名前でコンテナを作成し、起動します。初回のlaunchでは、サーバーからLXDイメージ(ルートファイルシステムとメタデータ)をダウンロードするためそれなりに時間がかかるはずです。ダウンロードしたデータはキャッシュされるので、以降は同じOS/アーキテクチャであれば比較的短時間で起動します。
execサブコマンドでは、指定したコンテナに対してrootでコマンドを実行します。今回は最初の2つでとりあえず起動したコンテナのパッケージ構成を最新にしています。後者2つで日本語ロケールにしていますが、こちらはなくてもかまいません。もちろんcloud-initなどで自動化することも可能です。
次のようにexecサブコマンドでbashを起動すれば、コンテナ内部でインタラクティブに操作できます。
$ lxc exec scratch /bin/bash
実行コマンドにオプションをつけたい場合は、コンテナ名の後ろに「--」をつけてください。
$ lxc exec scratch -- apt list --upgradable
後ほどssh接続するために、公開鍵も登録しておきましょう。方法としてはホストの公開鍵(~/.ssh/id_rsa.pub)をコンテナの~/.ssh/authorized_keysに記録するか、ホストに登録済みの鍵ファイル(~/.ssh/authrized_keys)を直接コンテナにコピーしてしまうことです。
fileサブコマンドを使うと、コンテナとホスト間のファイルのやり取りが便利になります。ホストからコンテナへファイルを送る場合は次のような書式になります。
$ lxc file push 送るファイルのパス コンテナ名/送り先のパス
authorized_keysをコピーするなら、次のように実行します。
$ lxc file push ~/.ssh/authorized_keys scratch/home/ubuntu/.ssh/
ちなみにUbuntuのコンテナイメージは、最初からsshサーバーが起動しています。既定のユーザー名は「ubuntu」です。
他の方法として、GitHubに登録済みの公開鍵をインポートしてしまうという手もあります。Ubuntuイメージなら最初からssh-import-idコマンドが用意されていますので、次のように実行してください。
$ lxc exec scratch -- ssh-import-id -o /home/ubuntu/.ssh/authorized_keys gh:m-shibata
「gh:GitHub上のユーザー名」で「https://api.github.com/users/ユーザー名/keys」にある公開鍵リストを「~/.ssh/authorized_keys」に登録してくれます。
Adobe AIRのインストール
32bitのUbuntu環境ができたので、さっそくAdobe AIRをインストールすることにしましょう。まずは依存するパッケージをインストールすることにします。
$ lxc exec scratch -- apt install -y libatk1.0-0 libc6 libcairo2 \
libdbus-1-3 libfontconfig1 libfreetype6 libgcc1 libglib2.0-0 \
libgtk2.0-0 libpango1.0-0 libpng12-0 libstdc++6 libx11-6 \
libxext6 libxml2 libxrender1 libxslt1.1 libxt6 zlib1g \
libgnome-keyring0 pulseaudio language-pack-ja fonts-takao
$ lxc exec scratch -- ln -s \
/usr/lib/i386-linux-gnu/libgnome-keyring.so.0 \
/usr/lib/libgnome-keyring.so.0
$ lxc exec scratch -- ln -s \
/usr/lib/i386-linux-gnu/libgnome-keyring.so.0.2.0 \
/usr/lib/libgnome-keyring.so.0.2.0
Adobe AIRはMultiArchに対応していないため、libgnome-keyringの共有ライブラリのリンクを作成しています。
Adobe AIRはヘッドレスインストールができません。X Window Systemが立ち上がっている必要があります。しかしながらコンテナの中でAdobe AIRのためだけにX Window Systemを立ち上げるのも冗長です。そこでSSHのFowardingX11オプションを使ってX転送することにします。
まずコンテナのIPアドレスを確認した上で、SSH接続しましょう。
$ lxc list scratch
+---------+---------+--------------------------------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------+---------+--------------------------------+------+------------+-----------+
| scratch | RUNNING | 10.0.4.1 (lxcbr0) | | PERSISTENT | 0 |
| | | 10.0.3.154 (eth0) | | | |
+---------+---------+--------------------------------+------+------------+-----------+
「lxc list」は作成済みのコンテナのリストを表示してくれます。引数にコンテナ名を渡すと、その名前でフィルタリングしてくれます。今回の場合はeth0の方のアドレスを使用します。
$ ssh -X [email protected]
もちろんコンテナ側にavahi-daemonをインストールして「scratch.local」を使ってアクセスするという手もあります。
$ lxc exec scratch apt install avahi-daemon
$ ssh -X [email protected]
以下、avahi-daemonが動いている前提で説明します。もし動かさない場合は「scratch.local」をコンテナのIPアドレスに置き換えてください。
以降はコンテナ内部の作業です。まずはAdobe AIRのインストーラーをダウンロードして実行権限をつけます。
$ wget http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRInstaller.bin
$ chmod +x AdobeAIRInstaller.bin
インストーラーは管理者権限で実行しなくてはならないのですが、Xの転送も必要です。そこで管理者に切り替わった上で、ubuntuユーザーのAuthorizationをマージします。
$ xauth list
scratch/unix:10 MIT-MAGIC-COOKIE-1 4fa5c4d1d6b5b7634a83f80263dbf2af
=> 現在有効なAuthorizationを表示している
$ sudo -i
# xauth merge ~ubuntu/.Xauthority
xauth: file /root/.Xauthority does not exist
最後のメッセージは「/root/.Xauthority」ファイルがないので、作成したということになります。この状態でX転送されるようになっていますので、Adobe AIRのインストーラーを起動しましょう。
# ~ubuntu/AdobeAIRInstaller.bin
図2 ライセンスの確認画面。問題なければ「I Agree」を押す
図3 インストール中。ネットワークの状況によっては数分かかる
図4 このダイアログが出たらインストールの完了
これでAdobe AIRのインストールは完了しました。なおファイルは「/opt/Adobe AIR」以下にインストールされます。半角空白がパスの中に入っているので、端末から中身を見る場合は気をつけてください。
Scratch 2.0のインストール
次にScratch 2.0をインストールします。Adobe AIRのアプリケーションはAdobe AIRのインストーラーを使ってインストールします。インストーラのコマンドは「/usr/bin/Adobe AIR Application Installer」です[4] 。ファイル名に半角空白が含まれているので適切にエスケープしないと実行できません。
[4] このファイル自体はシンボリックリンクで、実体はAlternativesシステムを使って、「 /opt/Adobe AIR/Versions/1.0/Adobe AIR Application Installer」を向いています。
Adobe AIRアプリケーションのインストール時も管理者権限が必要です。よってAdobe AIRと同様に管理者で作業を行います[5] 。
[5] 普通のデスクトップなら、必要に応じて(おそらく)gksuを使って権限を取得するため、インストーラーの実行そのものは管理者である必要はなさそうです。今回はLXDでそこまで動くようにする手間を考えると、より安直に管理者で実行した上で、システム領域にインストールするようにしています。
$ wget https://scratch.mit.edu/scratchr2/static/sa/Scratch-444.4.air
$ sudo -i
# xauth merge ~ubuntu/.Xauthority
xauth: file /root/.Xauthority does not exist
ダウンロードするファイル名は、Scratchサイトのダウンロードページ を参照してください。4月1日時点で、バージョンは444.4でした。前述したとおりインストーラーの実行ファイル名には空白が含まれているので、ダブルクオーテーションで括った上で実行しています。
# "Adobe AIR Application Installer" ~ubuntu/Scratch-444.4.air
図5 インストールの確認画面
図6 インストール先は「/opt」に、インストール後すぐにはアプリを起動しないようにしている
図7 インストール中。場合によってはシステムに負荷がかかる
図8 インストール完了
これでScratchのインストールは完了です。
Scratch 2.0を使う
ようやくScratch 2.0をインストールできたので、実際に起動してみましょう。ここからはホスト上での作業となります。
まずはScratch 2.0を起動してみましょう。といっても次のようにSSH経由で実行するだけです。
$ ssh -X [email protected] '/opt/Scratch\ 2/bin/Scratch\ 2'
Scratchもパスの中に半角空白が入っているのでいろいろとエスケープしなくてはなりません。のちほど、デスクトップファイルを作ってより簡単に起動する方法を紹介します。
初回起動時はライセンスの確認画面が表示されます。問題なければ「I Agree」をクリックしてください。わかりにくいですがこちらは「Adobe AIRを使ってアプリケーションを起動すること」に対する「Adobe Systems」との契約になります。Scratchは関係ありません。
図9 Adobe AIRインストール時とは少し異なる
また、Adobe AIRはアプリケーション起動時に「Adobe AIRそのもの」のアップデートの確認を行います。しかしながら、Linxu版はもう更新を提供していないこともあって、証明書関連の警告が表示されます。基本的に「Cancel」を押してアクセスしないようにしておきましょう。
図10 証明書が確認できない旨を通知するダイアログ
問題なく起動したらUIを日本語化します。画面左上の地球アイコンをクリックして、「 日本語」を選択してください。
図11 言語メニューから「日本語」を選択する
図12 ちなみに「にほんご」を選択するとすべてひらがなで表示してくれる
ファイルメニューからプロジェクトを保存するとコンテナの中の「/home/ubuntu/Scratch Projects」に保存されます。たとえばTest1.sb2をホストにコピーしたい場合は、次のように実行します。
$ lxc file pull "scratch/home/ubuntu/Scratch Projects/Test1.sb2" .
逆に「lxc file push」でホストのファイルをコンテナに送れます。Sambaでマウントさせたり、ホストの任意のディレクトリをコンテナの指定した場所にbind mountさせる方法もあります。コンテナとホスト間のプロジェクトファイルのやり取りについては、その用途にあわせてじっくり考えたほうがよいでしょう。
ちなみにファイルメニューから「Webサイトで共有」を選択すれば、作成したプロジェクトをScratchのサイトにアップロードできます。ただしいくつか制約 があるようです。
サウンド設定
コンテナの中にサウンドデバイスがないため、このままではScratchで音を鳴らそうとしても再生されません。方法としてはいくつか存在するのですが、今回はSSH経由でアクセスしているので、ホストのPulseAudioサーバーにコンテナからアクセスできるようにしてしまいましょう。
あらかじめコンテナの中にpulseaudioパッケージをインストールしておいてください。前述のAdobe AIRインストール時のパッケージリストをそのまま使っているなら、既にインストールされているはずです。
$ lxc exec scratch -- apt install -y pulseaudio
次にホスト上のPulseAudioサーバーの、TCP接続モジュールを有効化します。
$ cp /etc/pulse/default.pa ~/.config/pulse/
$ echo "load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;10.0.3.0/24" \
>> ~/.config/pulse/default.pa
$ pulseaudio -k
$ pulseaudio --check || echo "error"
最後の「pulseaudio --check」でエラーとなる場合は、何か設定が間違っているということになります。/var/log/syslogに表示されているログを確認してください。
Scratchを起動する際に、PulseAudioのサーバーのアドレス(つまりホストのアドレス)を指定します。コンテナから見ると、ホスト上のlxcbr0のアドレスがホストのアドレスになるので、環境変数PULSE_SERVERにその値を指定するだけです。
$ ssh -X [email protected] PULSE_SERVER=10.0.3.1 '/opt/Scratch\ 2/bin/Scratch\ 2'
「音」にあるサウンド再生系のブロックを使って、音を鳴ることを確認しておきましょう。
日本語入力の設定
ホスト側で適切に日本語入力の設定がなされているのであれば、コンテナ側は環境変数を設定するだけで、X転送経由の日本語入力を行えます。
$ ssh -X [email protected] XMODIFIERS=@im=fcitx '/opt/Scratch\ 2/bin/Scratch\ 2'
今回はAdobe AIRアプリなので「XMODIFIERS=@im=fcitx」のみ設定しています。IBusを使っている場合は、「 fcitx」を「ibus」に置き換えてください。
GTKアプリやQtアプリを動かす場合は、GTK_IM_MODULEやQT_IM_MODULEなどの設定も必要です。具体的な値については、ホストの環境変数を確認するとよいでしょう。
$ env | grep fcitx
QT_IM_MODULE=fcitx
XMODIFIERS=@im=fcitx
QT4_IM_MODULE=fcitx
GTK_IM_MODULE=fcitx
デスクトップファイルの作成
環境変数が増えてくると、コマンドラインで逐一指定するのが面倒になってきます。そこでデスクトップファイルを作って、UnityのDashから起動できるようにしてしまいましょう。
まずコンテナ側にScratchを起動するスクリプトを作成します。別にスクリプトを作成せずにホスト側のデスクトップファイルにすべて記述してもいいのですが、Scratchの起動に関して必要な情報はなるべくコンテナの中に入れておいたほうが、コンテナのマイグレーションなどの際に便利になるからです。
$ cat > scratch <<EOF
#!/bin/sh
export PULSE_SERVER=10.0.3.1
export XMODIFIERS=@im=fcitx
"/opt/Scratch 2/bin/Scratch 2"
EOF
$ chmod a+x scratch
$ lxc file push scratch scratch/usr/local/bin/
このスクリプトを使って起動し、サウンドの再生や日本語入力ができることを確認しておきましょう。
$ ssh -X [email protected] scratch
次にScratchのアプリケーションアイコンをホストに登録しましょう。
$ lxc file pull "scratch/opt/Scratch 2/share/icons/AppIcon128.png" mit-scratch.png
$ xdg-icon-resource install --size 128 mit-scratch.png
xdg-icon-resourceは「~/.local/share/icons/」以下の適切な場所にアイコンファイルをインストールしてくれます。
最後にデスクトップファイルをホストに作成します。
$ cat > scratch.desktop <<EOF
[Desktop Entry]
Name=scratch
GenericName=Scratch 2.0
Comment=Easy to use programming environment
Exec=ssh -X [email protected] scratch
Terminal=false
Type=Application
Icon=mit-scratch
Categories=Education;ComputerScience;
EOF
$ desktop-file-validate scratch.desktop
$ desktop-file-install --dir=$HOME/.local/share/applications/ scratch.desktop
desktop-file-validateはデスクトップファイルの検証ツールです。何か警告やエラーが表示されるようであれば、デスクトップファイルの仕様 を参考に適切に値を設定してください。desktop-file-installを実行によって、デスクトップファイルが登録され、Dash上に表示されるようになります。
以降はUnityのDashから「scratch」で検索して選択するだけで、Scratch 2.0を起動できますし、Launcherに登録することもできます。
アプリケーションコンテナの利便性
軽量な隔離環境でアプリケーションを動かせるコンテナ技術は、以下の用途の際に非常に便利です。
特定のディストリビューションでしか動かないアプリーケーションを動かしたいとき
あまりホストに特定のアプリケーションのためだけのパッケージやソフトウェアをインストールしたくないとき
ホストにPPAを追加したくないとき
古くあまり安全でないアプリケーションを動かさなくてはいけないとき
言うまでもなくDockerは、そのコンテナ技術を使ったアプリケーションコンテナを構築するツールの筆頭です。Dockerの登場によって、さまざまなサーバーソフトウェアをコンテナ内部で動かすようになってきました。実際、今回のような用途であればサーバーに限らずGUIアプリケーションであっても、Dockerを使って実現される方も多いでしょう。
GUIアプリケーションをより簡単にコンテナ化しようとする試みも存在します。たとえばGNOMEの「Sandboxed Applications 」はコンテナ技術とWaylandを用いて個々のアプリケーションを個別のサンドボックス環境で実行する仕組みです[6] 。他にもUbuntu 16.04 LTSからリポジトリに取り込まれた「adapt 」はまさしくLXDを使って、一時的に隔離環境を構築し、コマンドを実行してくれるツールです。ただしこちらは今のところCUIアプリケーションが専門です。いずれこれらのツールがより簡単にGUIコンテナを作ってくれるようになることでしょう。
[6] もともとは「XDG-App」という名前なのですが、他のGNOMEアプリケーションと同様にGNOMEプロジェクトではよりジェネリックな「Sandboxed Applications」という名前になっています。
今回のようにサポートの切れたAdobe AIRアプリケーションを動かしたいときや、Wineを使ってソースコードが不明なバイナリを起動しなくてはならない場合は、まずこのようなコンテナ技術を使って隔離することも考えてみてください。