はじめに
Debian noroot とは Android OS 上において root 権限を取ること無く、 Debian 環境を構築するためのアプリケーションです。
CPU の性能とメモリ容量が潤沢にある Android 端末であれば、 Debian noroot アプリの導入によって Android 端末上で非常に軽快な Debian 環境を実現することができます。
Debian noroot 環境において、一部の擬似端末を利用したソフトウェアがデバイスファイル /dev/ptmx を経由せずに擬似端末にアクセスしている為に正常に動作しない問題が発生しています。
そこで、 Android OS の C 標準ライブラリである bionic のソースコードから擬似端末関連の関数が含まれる C++ 言語のソースコードを抽出し、そのコードを完全な C 言語に修正した動的ライブラリのコードを作成しました。
そして、 Debian noroot 環境における C 標準ライブラリの擬似端末関連の関数を bionic 由来の関数に置き換えることにより、表記問題を回避することが出来ました。
本稿では、 Debian noroot 環境において一部の擬似端末を利用したソフトウェアが使用できない問題について、 C 標準ライブラリの擬似端末関連の関数を bionic 由来の関数に置き換えて問題を回避するための手法について述べます。
本稿では最初に、 "Debian noroot アプリについて" の章において、 Debian noroot アプリの概要について述べます。
次に、 "Debian noroot 環境にて擬似端末が使用できない問題" の章において、表題で述べられている問題について具体的に述べ、 "上記問題を回避する" の章において、問題の具体的な回避方法について述べます。
最後に、 "結論" の章において、今回の問題回避に関する結論について述べます。
Debian noroot アプリについて
Debian noroot とは、 Android OS 上において root 権限を取ることなく Debian 環境を構築するためのアプリケーションです。
CPU の性能とメモリ容量が潤沢にある Android OS 端末であれば、このアプリケーションの導入によって Android OS 端末上で非常に軽快な Debian 環境を実現できます。
現在、当方は手元の Sony Xperia Z Ultra 及び Everypad III 上に Debian noroot アプリをインストールして Android 上で Debian noroot 環境を運用しています。
Debian noroot 環境にて擬似端末が使用できない問題
ここで、 Debian noroot を使用する上で最も困る問題として /dev/pts/* 以下のデバイスファイルが叩けないために一部の擬似端末を利用したソフトウェアが使用できない問題が挙げられます。
具体的には、端末エミュレータのうち sakura が全く起動しない不具合や、 tmux や screen といった端末多重化ソフトウェアが動作しない不具合が発生しています。
この為に、多くのテキストベースのアプリケーションが導入できないか、もしくは導入が困難になり、非常に Debian noroot 環境の利便性が著しく低下していることが問題となっています。
上記問題を回避する
本章では、前章で述べた問題について、 C 標準ライブラリの擬似端末関連の関数を bionic 由来のコードの物に置き換える手法に基づいた、表記問題の具体的な回避手法について述べます。
本章では最初に、 "問題回避の概要" の節において、擬似端末が使用できない問題の回避についての概要について述べます。
次に、 "動的ライブラリのコンパイルとインストール" の節において、問題回避において用いる動的ライブラリのコンパイルとインストールの手法について述べます。
そして、 "設定と再起動" の節において、前節において行った動的ライブラリのインストール後に行う設定の手法について述べます。
最後に、 "Linuxbrew による問題回避" の節において、前々節及び前節において行った動的ライブラリのインストール及び設定を、ソースコードのビルドに基づいたパッケージ管理システムである Linuxbrew を用いて行う為の手法について述べます。
問題回避の概要
本節では、擬似端末が使用できない問題の回避について、擬似端末関連の C 標準ライブラリの置き換えに基づく具体的な手法の概要について述べます。
Android OS において、 Android OS の標準 C ライブラリである bionic や各種アプリケーションでは、擬似端末にアクセスする場合は、デバイスファイル /dev/ptmx を経由することになっています。
即ち、上記のような擬似端末が使用できない問題を回避するには、 C 標準ライブラリのうち、擬似端末関連の関数について、デバイスファイル /dev/ptmx を経由して擬似端末デバイスを操作する関数に置き換えれば良いということになります。
- https://raw.githubusercontent.com/android/platform_bionic/30a36273ab761fb07892f7816b4873b6c48a0cea/libc/bionic/pty.cpp
- https://raw.githubusercontent.com/android/platform_bionic/30a36273ab761fb07892f7816b4873b6c48a0cea/libc/private/ThreadLocalBuffer.h
そこで、 bionic より擬似端末関連の関数を含む上記の C++ 言語のソースコードを基に完全な C 言語に修正したコードを作成し、動的ライブラリとしてコンパイルしました。
そして、その C 言語のコードから生成した動的ライブラリを適切なパスにインストールした後、環境変数 LD_PRELOAD
に動的ライブラリのパスを追加することにより、これらの問題を回避することが可能になりました。
動的ライブラリのコンパイルとインストール
まずは Debian noroot 環境において、apt-get
コマンドにより、 Github のリポジトリを取得するための git 及びソースコードをダウンロードする為の wget と C++ のコードをコンパイルするための環境をインストールしておきます。
# apt-get install git wget
# apt-get install build-essential
次に、 Github 上にある当方が作成した C 言語のコードが置かれているリポジトリを git clone
により取得します。
# git clone https://github.com/z80oolong/libandroid-pty.git
その後、ディレクトリ ./libandroid-pty
にカレントディレクトリを移動して make
コマンドを実行し、動的ライブラリ libandroid-pty.so
が生成されていることを確認します。
# cd ./libandroid-pty
# make
arm-linux-gnueabihf-gcc -o libandroid-pty.so -fPIC -shared -Wall -Os -Wl,--version-script,libandroid-pty.map libandroid-pty.c -lpthread
arm-linux-gnueabihf-strip libandroid-pty.so
cp -p libandroid-pty.so libandroid-pty.so.arm
#
最後に、生成された動的ライブラリ libandroid-pty.so
を libandroid-shmem.so
等と同様にルートディレクトリにインストールします。
# make install INSTALL_DIR=/
もし、ソースコードをコンパイルする事が煩わしい場合や何らかの問題で困難である場合は、次に示す URL から下記のようにダウンロードして、 libandroid-pty.so.{arm,x86-32,x86-64}
を下記のようにルートディレクトリにインストールしても構いません。
- 安定版 (v0.1.1)
$ wget -O libandroid-pty.so.arm https://git.io/libandroid-pty.so-0.1.1.arm # (ARM 用のバイナリファイルのダウンロードの場合)
$ wget -O libandroid-pty.so.x86-32 https://git.io/libandroid-pty.so-0.1.1.x32 # (32 ビット x86 用のバイナリファイルのダウンロードの場合)
$ wget -O libandroid-pty.so.x86-64 https://git.io/libandroid-pty.so-0.1.1.x64 # (64 ビット x86 用のバイナリファイルのダウンロードの場合)
$ sudo install -m 0700 libandroid-pty.so.arm /libandroid-pty.so # (x86-32 搭載の端末の場合はinstall -m 0700 libandroid-pty.so.x86-32 /libandroid-pty.so)
# (x86-64 搭載の端末の場合はinstall -m 0700 libandroid-pty.so.x86-64 /libandroid-pty.so)
設定と再起動
前節で述べた動的ライブラリのインストールを行った後は、ルートディレクトリ直下にある /proot.sh
において、環境変数 LD_PRELOAD
の設定が書かれている行を下記のように修正して Debian noroot を再起動します。
...
# export "LD_PRELOAD=/libdisabledselinux.so /libandroid-shmem.so"
export "LD_PRELOAD=/libdisabledselinux.so /libandroid-shmem.so /libandroid-pty.so" # 末尾に /libandroid-pty.so を追加する。
...
再起動後は、 tmux, screen といった端末多重化ソフトウェアや sakura 等の一部のターミナルエミュレータをインストールしてこれらが正常に動作することを確認します。
Linuxbrew による問題回避
前々節及び前節において述べた擬似端末に関する問題回避のための動的ライブラリは、Linux の各ディストリビューション上におけるソースコードの取得及びビルドに基づいたパッケージ管理システムである Linuxbrew を利用することによっても導入を行うことが可能です。
本節では、 Linuxbrew に基づいて前述の動的ライブラリの導入を行い、問題回避のための設定を行う手法について述べます。
まずは、 "Debian noroot 環境に Linuxbrew を導入する" の投稿及び Linuxbrew の公式ページに基づいて Linuxbrew に依存するパッケージと Linuxbrew 本体のリポジトリを導入します。
$ sudo apt-get install build-essential curl file git python-setuptools ruby
$ sudo apt-get install m4 texinfo libbz2-dev libcurl4-openssl-dev libexpat-dev libncurses-dev zlib1g-dev gettext # 必要に応じて任意に導入する。
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install)"
なお、 32 bit ARM アーキテクチャ及び 64 bit x86 アーキテクチャ以外を搭載した携帯端末にインストールされた Debian noroot 環境に Linuxbrew を導入する場合、前述の Linuxbrew の本体のリポジトリを導入するコマンドを実行すると、途中で Linuxbrew が使用する ruby 処理系の bottle ファイルの取得に失敗して、導入作業が正常に行われません。
従って、これらの携帯端末における環境の場合は、 "Linuxbrew の自動的なインストールスクリプトが異常終了する場合における代替の導入手法" の投稿に基づき、 Linuxbrew の開発コミュニティによる Linuxbrew のインストールスクリプトに代えて、下記のようにして Linuxbrew を導入する必要が有ります。
$ sudo apt-get install build-essential curl file git python-setuptools ruby
$ sudo apt-get install m4 texinfo libbz2-dev libcurl4-openssl-dev libexpat-dev libncurses-dev zlib1g-dev gettext # 必要に応じて任意に導入する。
$ sudo apt-get install libssl-dev libreadline6-dev libyaml-dev libgdbm-dev libdb-dev
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/z80oolong/linuxbrew-altinstall/master/install.sh)"
そして、 bash
の初期化ファイルである ${HOME}/.bashrc
について、以下の通りに環境変数の設定を行い、 bashrc
を再起動します。
...
# for Linuxbrew
export HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew"
export PATH="${HOMEBREW_PREFIX}/sbin:${HOMEBREW_PREFIX}/bin:$PATH"
export MANPATH="${HOMEBREW_PREFIX}/share/man:${MANPATH}"
export INFOPATH="${HOMEBREW_PREFIX}/share/info:${INFOPATH}"
export HOMEBREW_NO_AUTO_UPDATE=1
...
次に、以下の通りに brew tap
コマンド及び brew install
コマンドを実行して、当方が作成した C 言語による動的ライブラリを導入します。
$ brew tap z80oolong/debian-noroot
$ brew install -dv z80oolong/debian-noroot/libandroid-pty
この時、ソースコードのコンパイルに若干時間が掛かると思われますが、我慢強くインストールの完了を待つ必要が有ります。
ここで、 brew install
コマンドの完了時に、以下のような Caveats
で始まるメッセージが表示されます。なお、このメッセージは brew info z80oolong/debian-noroot/libandroid-pty
を実行しても表示させることが出来ます。
...
==> Caveats
To use a preloaded dynamic library `libandroid-pty.so`, set environment variable LD_PRELOAD to `/home/linuxbrew/.linuxbrew/preload/libandroid-pty.so`:
for example:
$ export LD_PRELOAD="... /home/linuxbrew/.linuxbrew/preload/libandroid-pty.so"
or
$ /usr/bin/env LD_PRELOAD="... /home/linuxbrew/.linuxbrew/preload/libandroid-pty.so" linux_command
...
最後に、ルートディレクトリ直下にある /proot.sh
において、環境変数 LD_PRELOAD
の設定が書かれている行を下記のように修正して Debian noroot を再起動します。
...
# export "LD_PRELOAD=/libdisabledselinux.so /libandroid-shmem.so"
export HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew" # ここに、環境変数 HOMEBREW_PREFIX は、 Linuxbrew 本体のリポジトリのインストール先のディレクトリ。
export "LD_PRELOAD=/libdisabledselinux.so /libandroid-shmem.so ${HOMEBREW_PREFIX}/preload/libandroid-pty.so" # 末尾に ${HOMEBREW_PREFIX}/preload/libandroid-pty.so を追加する。
...
ここで、環境変数 LD_PRELOAD
に設定する動的ライブラリのパス名の設定は、必ず ${HOMEBREW_PREFIX}/preload/libandroid-pty.so
を用いることに注意して下さい。
これは、 Linuxbrew を用いて動的ライブラリを導入する際に、 brew install
コマンドが既存に導入した動的ライブラリを削除若しくは上書きすることを防ぎ、brew install
コマンドの完了まで既存の動的ライブラリを残すことで、 Debian noroot 環境全体が不具合を起こすのを防ぐ為です。
結論
Debian noroot 環境において、擬似端末を利用したソフトウェアが使用できない問題を回避するために、 bionic のソースコードから擬似端末関連の関数が含まれるソースコードを抽出して動的ライブラリとしてコンパイルし、環境変数 LD_PRELOAD
の設定を変更することにより、 Debian noroot 環境の C 標準ライブラリの擬似端末関連の関数を bionic 由来の関数に置換しました。
また、本稿で述べた一連の問題回避のための動的ライブラリのインストール及び設定に、 Linux の各ディストリビューション上におけるソースコードの取得及びビルドに基づいたパッケージ管理システムである Linuxbrew を利用することが有用であることも述べました。
これにより、 tmux, screen といった端末多重化ソフトウェアや sakura 等の一部のターミナルエミュレータが正常に動作し、上記問題を回避することが可能になったことを確認しました。
特にテキストベースのソフトウェアの多くが問題無く導入できるようになり、 Debian noroot の利便性が向上しました。
謝辞
本稿の記述に当たって、 bionic の開発に携わった Android Open Source Project に関わる全ての方々に心より感謝致します。
また、 Android OS 端末上で非常に軽快な Debian 環境を実現することを可能にした Debian noroot 環境の開発者である pelya 氏に心より感謝致します。
そして、本稿で述べた一連の問題回避のための動的ライブラリの導入にあたってパッケージ管理システムとして使用した Linuxbrew の導入に関しては thermes 氏による "Linuxbrew のススメ" 及び Linuxbrew の公式ページ等各種関連記事を参考にしました。 thermes 氏及び Linuxbrew の開発コミュニティの各氏に心より感謝致します。
最後に、 Debian noroot 環境と Android OS 及び Debian 環境の全ての事に関わる全ての皆様に心より感謝致します。
追記とお断り
2017/03/21 現在の追記とお断り
2017/03/21 現在の bionic のソースコードにおいて、 pthread における thread local buffer 関連の大幅なソースコードの変更に伴い、本稿の加筆及び修正を行いました。どうか御了承下さい。
2017/08/27 現在の追記
bionic のソースコードを基にした C 言語による動的ライブラリのコードの作成に伴い、本稿の修正を行いました。
2017/10/31 現在の追記
本稿において、 Linuxbrew を基にした問題回避のための動的ライブラリの導入に関する記述の追記を行いました。
2018/01/22 現在の追記とお断り
64 bit ARM アーキテクチャ等の環境で動作する Debian noroot 環境への Linuxbrew の導入に関する問題の解決手法について加筆を行い、本稿を改稿致しました。どうか御了承下さい。
2018/02/04 現在の追記とお断り
Linuxbrew を自動的にインストールするための代替となるスクリプトの作成と公開に伴い、本稿を改稿致しました。どうか御了承下さい。
2018/04/02 現在の追記とお断り
バイナリファイル libandroid-pty.so
を直接ダウンロードできる URL を追記しました。どうか御了承下さい。
2018/06/08 現在の追記とお断り
Linuxbrew を自動的にインストールするための代替となるスクリプトの更新と、代替スクリプトの実行手法の変更に伴い、本稿を改稿致しました。どうか御了承下さい。
2018/07/26 現在の追記とお断り
git リポジトリ版の動的ライブラリのバイナリファイルの同梱の廃止に伴い、本稿の改稿を行いました。改稿が遅れましたことを御詫び致しますと共に、どうか御了承下さいますよう御願い致します。
2018/10/11 現在の追記とお断り
Linuxbrew を自動的にインストールするための代替となるスクリプトの実行の際に、 Linuxbrew が使用する ruby 処理系をソースコードからコンパイルする際に必要となるパッケージについて訂正を行いました。どうか御了承下さい。
2018/12/12 現在の追記とお断り
"動的ライブラリのコンパイルとインストール" の節において、一部誤字が有りました。心より御詫び致しますと共に、本稿を訂正致しました。
2018/12/25 現在の追記とお断り
"Linuxbrew による問題回避" の節において、 Linuxbrew による libandroid-pty.so の導入手法について、大幅な簡略化に伴う変更がありましたので、当該節について改稿を行いました。