Debian noroot 環境に障害復旧用の環境を導入する

# はじめに

[Debian noroot][DBNR] とは、 [Android OS][ANDR] 上において root 権限を取ることなく [Debian 環境][DEBI]を構築するためのアプリケーションです。
CPU の性能とメモリ容量が潤沢にある Android 端末であれば、 [Debian noroot][DBNR] の導入によって Android 端末上で非常に軽快な [Debian 環境][DEBI]を実現することができます。

[Android OS][ANDR] からの [Debian noroot アプリ][DBNR]の起動時において、 **[Debian noroot 環境][DBNR]の起動画面の停止及び [Debian noroot アプリ][DBNR]全体の異常終了等により、 [Debian noroot 環境][DBNR]全体が完全に起動しなくなる障害が発生することがあります。**

ここで、 [Debian noroot 環境][DBNR]の起動過程について考えると、 "[Debian noroot 環境の動作原理について][ZOQ1]" の投稿で述べた通り、最初に [Xserver XSDL サーバ][XSDL]が起動された後、 [Android OS][ANDR] ネイティブ環境下において、 [Debian noroot 環境][DBNR]の初期設定と、 [Debian noroot 環境][DBNR]で使用する chroot 環境を構築するシェルスクリプトである ```/proot.sh``` が実行され、続いて、 proot.sh シェルスクリプトで構築した chroot 環境下において、デスクトップマネージャの起動等を行うシェルスクリプトである ```/startx.sh``` が実行されることにより、 [Debian noroot 環境][DBNR]が起動されることが判ります。

即ち、 [Debian noroot 環境][DBNR]の起動時に発生する障害の原因として、上記で述べたシェルスクリプト ```/proot.sh``` 及びシェルスクリプト ```/startx.sh``` の実行時に何らかの不具合が発生した事が可能性として考えられます。

以上で述べたような [Debian noroot 環境][DBNR]が正常に起動しない問題が発生すると、**最悪の状況では [Debian noroot 環境][DBNR]をクリーンインストールするか root 権限を取得しない限り、障害の復旧が不可能になる可能性が有ります。**

そこで、シェルスクリプト ```/proot.sh``` 及びシェルスクリプト ```/startx.sh``` の実行時に障害が発生した場合に備えて、 [Debian noroot 環境][DBNR]の障害復旧の為に、 　[Android OS][ANDR] からの [Debian noroot アプリ][DBNR]の起動時に標準的なターミナルエミュレータである ```xterm``` を単体かつ全画面で表示する環境を起動するシェルスクリプトを ```/proot-safe.sh``` 及び ```/startx-safe.sh``` として新たに作成しました。

そして実際に [Debian noroot 環境][DBNR]に問題が発生した際には、 [Debian noroot アプリ][DBNR]の起動直後に、[Debian noroot 環境][DBNR]を起動する為の一連のシェルスクリプトの実行過程に関する設定を修正することにより、 root 権限を取得すること無く [Debian noroot 環境][DBNR]の障害を復旧させる為の必要最小限の環境を起動させることが可能になりました。

本稿では、 [Debian noroot 環境][DBNR]の起動時に障害が発生した場合に、 [Debian noroot 環境][DBNR]の障害を回復させる為の必要最小限の環境を構築する手法と、 [Debian noroot 環境][DBNR]の障害復旧用の環境の実際の起動手法について述べます。

本稿では最初に、 "[障害復旧用のシェルスクリプトの作成][CHAP01]" の章において、 [Debian noroot 環境][DBNR]の障害復旧の為に必要最小限の環境を起動するシェルスクリプトの作成手法について述べます。

次に、 "[障害復旧用の環境の起動][CHAP02]" の章において、実際に [Debian noroot 環境][DBNR]に問題が発生した際等に [Debian noroot 環境][DBNR]の障害復旧用の環境を起動する手法について述べます。

最後に、 "[結論][CHAP03]" の章において、本稿の結論について述べます。

# 障害復旧用のシェルスクリプトの作成

本章では、 [Debian noroot 環境][DBNR]の障害復旧用の環境を起動する為のシェルスクリプトである ```proot-safe.sh``` 及び ```startx-safe.sh``` の作成手法について述べます。

本章では最初に、  "[/proot-safe.sh の作成][SEC0101]" の節において、シェルスクリプト ```/proot.sh``` の実行時に問題が発生した場合に、 ```/proot.sh``` に代えて起動するシェルスクリプトである ```/proot-safe.sh``` の作成手法について述べます。

次に、 "[/startx-safe.sh の作成][SEC0102]" の節において、 シェルスクリプト ```/startx.sh``` の実行時に問題が発生した場合に、 ```/startx.sh``` に代えて起動するシェルスクリプトである ```/startx-safe.sh``` の作成手法について述べます。

## /proot-safe.sh の作成

シェルスクリプト ```/proot.sh``` 時に障害が発生した場合、障害の原因として、 ```/proot.sh``` に記述されている [Android OS][ANDR] 上での初期設定及び [Debian noroot 環境][DBNR]を実行するための chroot 環境を構築する設定に問題が有る可能性が考えられます。

従って、 ```/proot.sh``` の障害を回避するには、問題の ```/proot.sh``` に代えて [Debian noroot アプリ][DBNR]がインストールされた初期状態における ```/proot.sh``` をシェルスクリプト ```/proot-safe.sh``` として実行すれば良い事が判ります。

ここで、シェルスクリプト ```/proot-safe.sh``` を作成するには、 [Debian noroot アプリ][DBNR]がインストールされた初期状態において、シェルスクリプト ```/proot.sh``` を以下のようにして ```/proot-safe.sh``` として保存します。

```shell-session
 # cp -p /proot.sh /proot-safe.sh
```

上記のようにシェルスクリプト ```/proot-safe.sh``` を保存した後は ```/proot-safe.sh``` の内容が下記の内容の通りであることを確認します。

```sh:/proot-safe.sh
#!/system/bin/sh

case x$SDCARD in x ) SDCARD=/sdcard;; esac

case x$SECURE_STORAGE_DIR in x ) echo > /dev/null;; * ) cd $SECURE_STORAGE_DIR/img;; esac

case x$SDCARD in x ) export SDCARD=$EXTERNAL_STORAGE;; esac

SDCARD=`../busybox realpath $SDCARD`
STORAGE="-b $SDCARD"
for F in 0 1 2 3 4 5 6 7 8 9; do
    DIR=`eval echo \\$UNSECURE_STORAGE_DIR_$F`
    case x$DIR in x ) echo > /dev/null;; * ) STORAGE="$STORAGE -b $DIR" ; mkdir -p $DIR ;; esac
done
echo "STORAGE $STORAGE"

export HOME=/home/$USER
export SHELL=/bin/bash
export LD_LIBRARY_PATH=
# Java doesn't work in PRoot when started from /usr/bin/java symlink, so we have to put a path to java binary into PATH, and Java 6 fails on Samsung devices
JAVA_PATH=/usr/lib/jvm/default-java/jre/bin:/usr/lib/jvm/default-java/bin
ls usr/lib/jvm/java-7-openjdk-*/bin > /dev/null 2>&1 && JAVA_PATH=/`echo usr/lib/jvm/java-7-openjdk-*/jre/bin`:/`echo usr/lib/jvm/java-7-openjdk-*/bin`
export PATH=/usr/local/sbin:/usr/local/bin:$JAVA_PATH:/usr/sbin:/usr/bin:/sbin:/bin
export "LD_PRELOAD=/libdisableselinux.so /libandroid-shmem.so"
export PROOT_TMPDIR=`pwd`/tmp
export PROOT_TMP_DIR=$PROOT_TMPDIR
export TZ="`getprop persist.sys.timezone`"
./proot -r `pwd` -w / -b /dev -b /proc -b /sys -b /system $STORAGE "$@"
```

なお、 ```/proot-safe.sh``` は、以下の内容のように初期状態の ```/proot.sh``` より少ない設定内容で作成することも可能です。

```sh:/proot-safe.sh
#!/system/bin/sh

case x$SECURE_STORAGE_DIR in x ) echo > /dev/null;; * ) cd $SECURE_STORAGE_DIR/img;; esac

case x$SDCARD in x ) export SDCARD=$EXTERNAL_STORAGE;; esac

SDCARD=`../busybox realpath $SDCARD`
STORAGE="-b $SDCARD"

export HOME=/home/$USER
export SHELL=/bin/bash
export LD_LIBRARY_PATH=
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export "LD_PRELOAD=/libdisableselinux.so /libandroid-shmem.so"
export PROOT_TMPDIR=`pwd`/tmp
export PROOT_TMP_DIR=$PROOT_TMPDIR
export TZ="Asia/Tokyo"
./proot -r `pwd` -w / -b /dev -b /proc -b /sys -b /system $STORAGE "$@"
```

何れの場合でも、最後には以下の通りにして、シェルスクリプト ```/proot-safe.sh``` がユーザに対して実行権限が付与されている事を確認します。

```shell-session
 # chmod u+x /proot-safe.sh
 # ls -l /proot-safe.sh
 -rwx------. 1 user user 716  5月 13 13:05 /proot-safe.sh    # (ユーザ及びファイルサイズ等は環境によって異なります。)
 #
```

## /startx-safe.sh の作成

シェルスクリプト ```/startx.sh``` 時に障害が発生した場合、障害の原因として、 ```/startx.sh``` に記述された設定の問題の他に、[Debian noroot 環境][DBNR]上のデスクトップマネージャの各種設定等に問題が存在する可能性が考えられます。

従って、 ```/startx.sh``` の障害を回避するには、問題の ```/startx.sh``` に代えて、  [Debian noroot 環境][DBNR]上のデスクトップマネージャを起動すること無く、標準的なターミナルエミュレータである ```xterm``` を単体かつ全画面で表示させる環境を起動するシェルスクリプトを ```/startx-safe.sh``` として実行すれば良いことが判ります。

ここで、シェルスクリプト ```/startx-safe.sh``` を作成するには、 ```/startx-safe.sh``` の内容を下記の通りに作成します。

```sh:/startx-safe.sh
#!/bin/sh

rm -f $HOME/.config/xfce4/xfconf/xfce-perchannel-xml/keyboard-layout.xml
(LANG=C LC_ALL=C LANGUAGE=en /usr/bin/xterm -fn 10x20 -maximized -bg black -fg green -e /bin/bash) || true
setsid sh -c "cd /proc/ ; for f in [0-9]* ; do [ \$f = \$\$ ] || kill -9 \$f ; done"

wait
```

そして最後に、以下の通りにしてシェルスクリプト ```/startx-safe.sh``` がユーザに対して実行権限が付与されている事を確認します。

```shell-session
 # chmod u+x /startx-safe.sh
 # ls -l /startx-safe.sh
 -rwx------. 1 user user 282  5月 13 13:05 /startx-safe.sh    # (ユーザ及びファイルサイズ等は環境によって異なります。)
 #
```

# 障害復旧用の環境の起動

本章では、[前章][CHAP01]において作成したシェルスクリプト ```/proot-safe.sh``` 及び ```/startx-safe.sh``` を用いて、実際に障害復旧用の環境を起動する手法について述べます。

最初に、[Android OS][ANDR] からの [Debian noroot アプリ][DBNR]の起動時に、 "[Debian noroot 環境の動作原理について][ZOQ1]" の投稿で述べた "[Xserver XSDL サーバの起動コマンドラインを表示する][ZOQ2]" を参考にして、以下の手順に基づいて [Xserver XSDL サーバ][XSDL]の起動コマンドラインを表示させます。

- [Debian noroot アプリ][DBNR]の起動画面が表示された直後に画面上部の **"Change device config" ボタンをクリックすると、 "Device configuration" なるタイトルのメニューが表示されます。**
- "Device configuration" メニューが表示された状態から "Device configuration" メニューより **"Data installation location" を選択すると、 "Data installation location" メニューが表示されます。**
- "Data install location" メニューが表示された状態から **"Specify directory" を選択すると、 "Specify directory" メニューが表示され、**ディレクトリの変更を促されますが、このまま**何もせずに "OK" ボタンを押します。**
- "Specify directory" メニューから "OK" ボタンを押すと、 **"Specify command line parameters" メニューに以下の画像のようなコマンドラインが表示されます。**

![("Specify command line parameters" メニュー)][IMG1]

"[Debian noroot 環境の動作原理について][ZOQ1]" の投稿で述べた通り、上記のコマンドラインの内容が [Debian noroot アプリ][DBNR]によって [Xserver XSDL サーバ][XSDL]が起動される際に [Xserver XSDL サーバ][XSDL]のコマンド ```XSDL``` に渡されるオプション及び引数であり、[Debian noroot 環境][DBNR]上のデスクトップマネージャが起動するまでの一連のシェルスクリプトの実行過程であることが判ります。

ここで、 [Debian noroot 環境][DBNR]の障害が ```/proot.sh``` の実行に起因している場合は、以下のように  "Specify command line parameters" メニューに示されるコマンドラインにおいて、 ```proot.sh``` 及び ```startx.sh``` の部分をそれぞれ ```proot-safe.sh``` 及び ```startx-safe.sh``` と修正します。

```shell-session
 XSDL -nohelp -screenbuttons -warndiskspacemb 900 -exec $SECURE_STORAGE_DIR/usr/bin/xli -onroot -border black -center $UNSECURE_STORAGE_DIR/loading.gif ; $SECURE_STORAGE_DIR/img/proot-safe.sh ./startx-safe.sh
```

また、 [Debian noroot 環境][DBNR]の障害が ```/startx.sh``` の実行に起因している場合は、以下のように "Specify command line parameters" メニューに示されるコマンドラインにおいて、 ```startx.sh``` の部分を ```startx-safe.sh``` と修正します。

```shell-session
 XSDL -nohelp -screenbuttons -warndiskspacemb 900 -exec $SECURE_STORAGE_DIR/usr/bin/xli -onroot -border black -center $UNSECURE_STORAGE_DIR/loading.gif ; $SECURE_STORAGE_DIR/img/proot.sh ./startx-safe.sh
```

以上の修正を行った後は、 "Specify command line parameters" メニューから "OK" ボタンを押します。その後は、 "Device Configuration" メニューに画面が遷移するので、"Device Configuration" メニューより "OK" を選択します。

そして、 "Device Configuration" メニューより "OK" を選択した後は、 [Debian noroot 環境][DBNR]の一連の起動過程が開始され、以下の画面のように、デスクトップマネージャが起動せずに全画面で ```xterm``` が起動する環境が起動します。

![(障害回復用の環境)][IMG2]

[Debian noroot 環境][DBNR]で発生した障害の回復が完了した後は、 ["Specify command line parameters" メニューに示されるコマンドライン][IMGID0202]を以下の通りに、元の状態のコマンドラインに修正します。

```shell-session
 XSDL -nohelp -screenbuttons -warndiskspacemb 900 -exec $SECURE_STORAGE_DIR/usr/bin/xli -onroot -border black -center $UNSECURE_STORAGE_DIR/loading.gif ; $SECURE_STORAGE_DIR/img/proot.sh ./startx.sh
```

# 結論

本稿では、シェルスクリプト ```/proot.sh``` 及び ```/startx.sh``` の起動時に問題が発生し、 [Debian noroot 環境][DBNR]の起動に障害が発生した場合に備えて、 [Debian noroot 環境][DBNR]の障害復旧の構築を行いました。

最初に、 [Debian noroot アプリ][DBNR]がインストールされた初期状態における ```/proot.sh``` の内容若しくは初期状態の ```/proot.sh``` を元にして必要最小限の設定が記述されたシェルスクリプトを ```/proot-safe.sh``` として作成しました。

次に、 [Debian noroot 環境][DBNR]のデスクトップマネージャを起動すること無く、標準的なターミナルエミュレータである ```xterm``` を単体かつ全画面で表示する環境を起動するシェルスクリプトを ```/startx-safe.sh``` として作成しました。

そして実際に [Debian noroot 環境][DBNR]に問題が発生した際には、 [Debian noroot 環境][DBNR]の起動設定メニューのうち "Specify command line parameters" メニューに記述されているコマンドラインの内容において、 ```/proot.sh``` 及び ```/startx.sh``` が起動する部分を ```/proot-safe.sh``` 及び ```/startx-safe.sh``` が起動するように修正することにより、 root 権限を取得すること無く [Debian noroot 環境][DBNR]の障害復旧の為の必要最小限の環境を起動させることが可能になりました。

本稿において示した [Debian noroot 環境][DBNR]の障害復旧用の環境を導入することにより、  **[Debian noroot 環境][DBNR]のクリーンインストールによる重大なデータ及び設定の喪失等を伴うこと無く、安全に障害復旧の作業を行うことが可能となります。**

[Android OS][ANDR] に [Debian noroot アプリ][DBNR]をインストールした際には、**本稿で述べた障害復旧用の環境を導入して、 Debian oroot 環境の起動時の障害に備えておくことを強く御勧め致します。**

# 謝辞

本稿の記述に当たって、 [Android OS][ANDR] 端末上で非常に軽快な [Debian 環境][DEBI]を実現することを可能にした [Debian noroot 環境][DBNR]の開発者である [pelya 氏][PELY]に心より感謝致します。

最後に、 [Debian noroot 環境][DBNR]と [Android OS][ANDR] 及び [Debian 環境][DEBI]の全ての事に関わる全ての皆様に心より感謝致します。

<!-- 各章及び各節へのリンク一覧 -->

[CHAP01]:#障害復旧用のシェルスクリプトの作成
[CHAP02]:#障害復旧用の環境の起動
[CHAP03]:#結論
[SEC0101]:#proot-safesh-の作成
[SEC0102]:#startx-safesh-の作成

<!-- 外部リンク一覧 -->

[DBNR]:https://play.google.com/store/apps/details?id=com.cuntubuntu&hl=ja
[ANDR]:https://www.android.com/intl/ja_jp/
[DEBI]:https://www.debian.org/index.ja.html
[ZOQ1]:http://qiita.com/z80oolong/items/4ef119a6af79a9276a0d
[ZOQ2]:http://qiita.com/z80oolong/items/4ef119a6af79a9276a0d#xserver-xsdl-サーバの起動コマンドラインを表示する
[XSDL]:https://play.google.com/store/apps/details?id=x.org.server&hl=ja
[IMG1]:https://qiita-image-store.s3.amazonaws.com/0/86258/03a639f2-0b1a-2cef-1894-563c6698db07.jpeg
[IMG2]:https://qiita-image-store.s3.amazonaws.com/0/86258/236e2632-7e77-51b9-25f2-22f9fea3c21d.png
[PELY]:https://github.com/pelya