Android
Bash
Linux
Termux

Termuxでシェルスクリプトを改変なしに実行できるようにしてみる

Termuxとは

Termuxはroot権限なしにLinuxのコマンドライン環境を実現するAndroidのアプリ。ちょっと古めのスマートフォンやタブレットでもサクサク。VimやClangをはじめ、wget、curl、rsyncなどたくさんのツールが動作し、いつでもどこでも思い立ったらコーディングできます。

ただし、ディレクトリ構造はシミュレートしないのでLinuxの/に相当するパスは/data/data/com.termux/filesになってしまうという制限があります。今日はそれをなんとかしてみます。

PREFIX環境

Termuxは自身のWikiに書いてあるようにPREFIX環境です。

PREFIX=/data/data/com.termux/files
HOME=/data/data/com.termux/files/home

以上の2つの環境変数が予め設定されており、たとえば
/etcディレクトリへ行く場合cd $PREFIX/etcのように/etc$PREFIX/etcと変換して入力する必要があります。なので、実際にはcd /data/data/com.termux/files/usr/etcを実行していることになります。

問題点

ホームディレクトリ以外へ行くときはたまに設定をいじったりする程度なので頻度は高くないです。しかし、シェルスクリプトを実行するときに

#!/bin/sh

と、書いてしまうと、そんなものは存在しないと怒られます。そのためにTermuxにはtermux-fixshebangコマンドが用意されており、termux-fixshebang script.shと実行することで

#!/data/data/com.termux/files/usr/bin/sh

へ変換してくれます。ただ、これだと他のPCにシェルスクリプトを持っていくときに修正する必要があります。きっと一番大事なときに書き換えるのを忘れてしまいます。僕は絶対に忘れる自信があります。

方法1: termux-chroot

Termuxのリポジトリにはprootというパッケージがあり、chrootして一般的なLinuxと同じディレクトリ構造をシミュレートしてくれます。なので、新しいターミナルを開いたらこれを実行するようにしておけば全く違和感なく利用できます。
$PREFIX/etc/profileの最初に以下のコードを追加しておけばターミナルを開いたら勝手にchrootしてくれます。

/etc/profile
# シェルの深さが1ならchrootする
[ $SHLVL = 1 ] && termux-chroot
# ...

これで解決だと思いきや、自分の環境(Xiaomi Redmi Note 4/Android 6.0 MIUI 8/MT6797 Helio X20/3GB RAM)ではコマンド実行時に顕著にレスポンスが悪くなってしまいます。たとえば、いつもはhtopを叩くとすぐに起動していましたが、termux-chroot実行後は画面が表示されるまで1秒以上待たされます。

方法2: rootを取る

グローバル展開しているAndroid端末ならrootが取れないものなんてあまりないですよね。というか、rootが取れない端末なんて買わないですよね。UbuntuでWifiが動作しないPCを買わないのと一緒です。とは言うものの、root権限なしでLinux環境と謳っているTermuxのコンセプトに反するのは後ろめたいですが。
rootを取ってSuperSUをインストールする部分はそれぞれの端末で異なりますので割愛します。

# rootfsをrwでマウント
mount -o remount,rw /

# シンボリックリンクを作る
cd /bin
ln -s /data/data/com.termux/files/usr/bin/sh
ln -s /data/data/com.termux/files/usr/bin/bash

# "#!/usr/bin/env python"も実行できるようにする
# "/usr"以下は存在しないので、作成してパーミッションも変更
mkdir -p /usr/bin
chmod a+rx /usr/bin
cd /usr/bin
ln -s /data/data/com.termux/files/usr/bin/env

# rootfsをreadonlyでマウント
mount -o remount,r /

/usrが存在しないのでディレクトリを作成した後はパーミッションを変更しておくのを忘れないようにしましょう。あとはSuperSUのFull Unrootを実行すればもとのセキュアな環境に戻れます。