Anbox 安裝過程分析
Anbox 是在像 Ubuntu 這樣的普通 GNU/Linux 系統(tǒng)上座咆,基于容器啟動(dòng)完整 Android 系統(tǒng)的方案。
當(dāng)前安裝過程由多個(gè)步驟組成黎比,這些步驟將向主機(jī)系統(tǒng)中添加額外的組件,這些組件包括:
- 由于沒有發(fā)行版內(nèi)核同時(shí)啟用 binder 和 ashmem,因此需要它們的源碼樹之外的內(nèi)核模塊
- 為
/dev/binder
和/dev/ashmem
設(shè)置正確權(quán)限的 udev 規(guī)則 - upstart 或 systemd 任務(wù),用于作為用戶會(huì)話的一部分啟動(dòng) Anbox 會(huì)話管理器磺芭。
為了使 Anbox 的安裝過程盡可能簡(jiǎn)單,Anbox 官方已經(jīng)在一個(gè) snap (參考 https://snapcraft.io) 中打包了必須的步驟醉箕,稱為 "anbox-installer"钾腺。這個(gè)安裝器將執(zhí)行所有必須的步驟〖タ悖可以通過運(yùn)行如下命令放棒,在系統(tǒng)上安裝 Anbox 提供對(duì) snaps 的支持:
$ snap install --classic anbox-installer
另外,還可以通過如下命令獲得安裝器腳本:
$ wget https://raw.githubusercontent.com/anbox/anbox-installer/master/installer.sh -O anbox-installer
要通過 Anbox 的安裝器腳本安裝 Anbox 的話己英,簡(jiǎn)單地調(diào)用即可:
$ anbox-installer
這將指導(dǎo)我們完成安裝過程间螟。
anbox-installer
安裝器腳本的實(shí)現(xiàn)是這樣的:
#!/bin/bash
echo "Anbox (Android in a Box) - Installer"
echo
echo
echo "IMPORTANT: THIS IS ALPHA LEVEL SOFTWARE. EXPECT INSTABILITY AND"
echo " BUGS !!!!!"
echo
echo "IMPORTANT: ALSO PLEASE BE AWARE THAT WE DON'T PROVIDE FULL"
echo " CONFINEMENT FOR THE SNAP YET !!!!"
echo
echo
echo "PLEASE NOTE: This script will require root access on your system"
echo "to install all necessary things. It will prompt you to enter your"
echo "password when required."
echo
echo
if [ "$(id -u)" -eq 0 ] ; then
echo "ERROR: Don't run the anbox-installer as root or via sudo. Simply"
echo " invoke it with your regular user. The script will use sudo"
echo " on its own when needed."
exit 1
fi
if ! uname -a | grep -q x86_64 ; then
echo "ERROR: We only have support for x86 64 bit devices today. As"
echo " your system has a different architecture we can't"
echo " support it yet."
exit 1
fi
SUPPORTED_DISTROS=("Ubuntu" "LinuxMint" "neon" "elementary" "Zorin")
DISTRIB_ID="$(lsb_release -i -s)"
function contains() {
local n=$#
local value=${!n}
for ((i=1;i < $#;i++)) {
if [ "${!i}" == "${value}" ]; then
echo "y"
return 0
fi
}
return 1
}
if [ "$(contains "${SUPPORTED_DISTROS[@]}" "$DISTRIB_ID")" != "y" ]; then
echo "ERROR: You are running the installer on an unsupported distribution."
echo " At the moment we only support the following distributions:"
echo
printf "%s, " "${SUPPORTED_DISTROS[@]}" | cut -d "," -f 1-${#SUPPORTED_DISTROS[@]}
echo
echo "If your distribution is in the list but you still see this message, open"
echo "an issue here: https://github.com/anbox/anbox-installer"
exit 1
fi
echo
echo "What do you want to do?"
echo
echo " 1. Install Anbox"
echo " 2. Uninstall Anbox"
echo
echo "Please enter your choice [1-2]: "
read -r action
echo
echo
[[ -n "$(which snap)" ]] || {
echo "ERROR: Your system does not support snaps. Please have a look"
echo " at https://snapcraft.io/ to find out how you can add"
echo " support for snaps on your system."
exit 1
}
uninstall() {
set -x
sudo snap remove anbox
if [ -e /etc/apt/sources.list.d/morphis-ubuntu-anbox-support-xenial.list ]; then
ppa_purged_installed=0
if ! dpkg --get-selections | grep -q ppa-purge ; then
sudo apt install -y ppa-purge
ppa_purged_installed=1
fi
sudo apt install -y ppa-purge
sudo ppa-purge -y ppa:morphis/anbox-support
if [ "$ppa_purged_installed" -eq 1 ]; then
sudo apt purge ppa-purge
fi
fi
set +x
}
if [ "$action" == "2" ]; then
echo "This will now remove the Android in a Box runtime environment"
echo "from your device. Do you really want this?"
echo
echo "Please be aware that this will also remove any user data"
echo "stored inside the runtime environment."
echo
echo "Please type 'I AGREE' followed by pressing ENTER to continue"
echo "or type anything else to abort:"
read -r input
if [ "$input" != "I AGREE" ]; then
exit 1
fi
echo
uninstall
echo
echo "Successfully removed anbox!"
echo
exit 0
fi
if [ "$action" != "1" ]; then
echo "ERROR: Invalid option selected!"
exit 1
fi
echo "This is the installer for the anbox runtime environment. It will"
echo "install certain things on your system to ensure all requirements"
echo "are available for anbox to work correctly."
echo
echo "In summary we will install the following things:"
echo
echo " * Add the anbox-support ppa ppa:morphis/anbox-support to the"
echo " host system"
echo " * Install the anbox-modules-dkms deb package from the ppa"
echo " which will add kernel modules for ashmem and binder which are"
echo " required for the Android container to work."
echo " * Configure binder and ashmem kernel modules to be loaded"
echo " automatically on boot."
echo " * Install the anbox-common package from the ppa which will"
echo " - Add an upstart job for the current user $USER which will"
echo " start the anbox runtime on login."
echo " - Add a X11 session configuration file to allow the system"
echo " application launcher (Unity7, Gnome Shell, ..) to find"
echo " available Android applications."
echo
echo "Please type 'I AGREE' followed by pressing ENTER to continue"
echo "or type anything else to abort:"
read -r input
if [ "$input" != "I AGREE" ]; then
exit 1
fi
echo
echo
echo "Starting installation process ..."
echo
cleanup() {
local err=$?
trap - EXIT
echo "ERROR: Installation failed. Removing all parts of Anbox again."
uninstall
exit $err
}
trap cleanup HUP PIPE INT QUIT TERM EXIT
set -ex
sudo add-apt-repository -y 'ppa:morphis/anbox-support'
# Users tend to have APT repositories installed which are not properly
# authenticated and because of that `apt update` will fail. We ignore
# this and proceed with the package installation. If the installation
# of a specific package fails this will indicate our point of abort.
sudo apt update || true
sudo apt install -y anbox-common
# Install kernel drivers only if necessary and let the user use the
# ones build into his kernel otherwise.
if [ -c /dev/binder ] && [ -c /dev/ashmem ]; then
echo "Android binder and ashmem seems to be already enabled in kernel.";
else
sudo apt install -y linux-headers-generic anbox-modules-dkms
sudo modprobe binder_linux
sudo modprobe ashmem_linux
fi
if snap info anbox | grep -q "installed:" ; then
sudo snap refresh --edge anbox || true
else
sudo snap install --edge --devmode anbox
fi
set +x
echo
echo "Done!"
echo
echo "To ensure all changes made to your system you should now reboot"
echo "your system. If you don't do this no Android applications will"
echo "show up in the system application launcher."
trap - EXIT
anbox-installer
安裝器腳本中的 echo 打印輸出有點(diǎn)多,同時(shí)這個(gè)腳本還提供了移除 anbox 的功能损肛。安裝 Anbox 的工作主要由如下這幾行代碼完成:
sudo add-apt-repository -y 'ppa:morphis/anbox-support'
. . . . . .
sudo apt update || true
sudo apt install -y anbox-common
# Install kernel drivers only if necessary and let the user use the
# ones build into his kernel otherwise.
if [ -c /dev/binder ] && [ -c /dev/ashmem ]; then
echo "Android binder and ashmem seems to be already enabled in kernel.";
else
sudo apt install -y linux-headers-generic anbox-modules-dkms
sudo modprobe binder_linux
sudo modprobe ashmem_linux
fi
if snap info anbox | grep -q "installed:" ; then
sudo snap refresh --edge anbox || true
else
sudo snap install --edge --devmode anbox
fi
set +x
. . . . . .
trap - EXIT
這段代碼厢破,通過三個(gè)步驟完成 Anbox 的安裝。
第一步治拿,安裝 anbox-common
sudo add-apt-repository -y 'ppa:morphis/anbox-support'
. . . . . .
sudo apt update || true
sudo apt install -y anbox-common
anbox-common
包的安裝的文件如下:
$ dpkg -L anbox-common
/.
/etc
/etc/X11
/etc/X11/Xsession.d
/etc/X11/Xsession.d/68anbox
/usr
/usr/share
/usr/share/doc
/usr/share/doc/anbox-common
/usr/share/doc/anbox-common/README.Debian
/usr/share/doc/anbox-common/changelog.gz
/usr/share/doc/anbox-common/copyright
/usr/src
第二步摩泪,安裝 binder 和 ashmem 驅(qū)動(dòng)
sudo apt install -y linux-headers-generic anbox-modules-dkms
sudo modprobe binder_linux
sudo modprobe ashmem_linux
第三步,通過 snap 的方式安裝 anbox 包
sudo snap install --edge --devmode anbox
anbox 包通過 snap 的方式進(jìn)行安裝劫谅。
Anbox 容器管理服務(wù)
整體看來见坑,Anbox 的安裝過程安裝了兩個(gè)組件,一是 binder 和 ashmem 內(nèi)核驅(qū)動(dòng)捏检;二是 Anbox荞驴,Anbox 又由 anbox-common 和 anbox snap 組成。
通過如下命令可以看到 anbox snap 的信息:
$ snap info anbox
name: anbox
summary: Android in a Box
publisher: morphis
description: |
Runtime for Android applications which runs a full Android system
in a container using Linux namespaces (user, ipc, net, mount) to
separate the Android system fully from the host.
snap-id: Nr9K6UJaIOD8wHpDEQl16nabFFt9LLEQ
commands:
- anbox
- anbox.collect-bug-info
services:
anbox.container-manager: simple, enabled, inactive
tracking: edge
installed: 3-7266fe2 (65) 361MB devmode
refreshed: 2017-11-17 21:37:23 +0800 CST
channels:
stable: –
candidate: –
beta: 1-dev (15) 357MB devmode
edge: 3-7266fe2 (65) 361MB devmode
anbox 向主機(jī)系統(tǒng)中安裝了 2 個(gè)命令贯城,anbox
和 anbox.collect-bug-info
戴尸,以及一個(gè) service,anbox.container-manager
冤狡,即 Anbox 的容器管理器服務(wù)孙蒙。
通過 Anbox 安裝器安裝 Anbox 之后,service 會(huì)自動(dòng)啟動(dòng)悲雳。通過如下命令可以查看這個(gè)服務(wù)的當(dāng)前狀態(tài):
$ sudo systemctl status snap.anbox.container-manager
● snap.anbox.container-manager.service - Service for snap application anbox.container-manager
Loaded: loaded (/etc/systemd/system/snap.anbox.container-manager.service; enabled; vendor preset: enabled)
Active: active (running) since 五 2017-12-01 09:55:46 CST; 3min 54s ago
Process: 25619 ExecStop=/usr/bin/snap run --command=stop anbox.container-manager (code=exited, status=0/SUCCESS)
Main PID: 30438 (anbox)
Tasks: 10
Memory: 1.8M
CPU: 74ms
CGroup: /system.slice/snap.anbox.container-manager.service
├─30438 /snap/anbox/65/usr/bin/anbox container-manager --data-path=/var/snap/anbox/common/ --android-image=/snap/anbox/
└─30644 [lxc monitor] /var/snap/anbox/common/containers default
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + [ ! -e /snap/anbox/65/android.img ]
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + start
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + mkdir -p /var/snap/anbox/common/lxc
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + /snap/anbox/65/bin/anbox-bridge.sh start
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + echo Y
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + tee /sys/module/fuse/parameters/userns_mounts
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: Y
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + AA_EXEC=/snap/anbox/65/usr/sbin/aa-exec -p unconfined --
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + [ ! -d /sys/kernel/security/apparmor ]
12月 01 09:55:46 ThundeRobot anbox.container-manager[30438]: + exec /snap/anbox/65/usr/sbin/aa-exec -p unconfined -- /snap/anbox/65
當(dāng) Anbox 的容器管理服務(wù)正常運(yùn)行時(shí)挎峦,通過在應(yīng)用列表中,點(diǎn)擊 Anbox 應(yīng)用合瓢,如下圖這樣:
可以啟動(dòng) Anbox 會(huì)話坦胶。
當(dāng) Anbox 的容器管理服務(wù)起動(dòng)時(shí),它會(huì)監(jiān)聽一個(gè) Unix 域 Socket,/run/anbox-container.socket
顿苇。(這個(gè)地址在 anbox/src/anbox/container/service.cpp
文件的 Service::create()
函數(shù)中峭咒,從 anbox::SystemConfiguration::container_socket_path()
獲得)。
當(dāng)啟動(dòng) Anbox 應(yīng)用纪岁,即會(huì)話管理器時(shí)凑队,它會(huì)通過 Unix 域 Socket 與容器管理服務(wù)建立連接。容器管理服務(wù)接收到連接幔翰,且容器還沒有啟動(dòng)時(shí)漩氨,它會(huì)掛載 Android 系統(tǒng)鏡像,起動(dòng) LXC 容器遗增,并在容器內(nèi)起動(dòng) Android 系統(tǒng)叫惊。
同時(shí)會(huì)話管理器與主機(jī)系統(tǒng)上的 ADB 服務(wù)建立連接。如:
$ ps -aux | grep anbox
hanpfei+ 15883 3.3 1.0 3024640 175500 ? Sl 19:01 0:34 /usr/bin/python3 /usr/bin/remarkable /home/hanpfei0306/data/MyProjects/hanpfei-documents/source/_posts/anbox_container_manager_service.md
root 16732 0.1 0.0 569980 12288 ? Ssl 19:17 0:00 /snap/anbox/x1/usr/bin/anbox container-manager --data-path=/var/snap/anbox/common/ --android-image=/snap/anbox/x1/android.img --daemon
hanpfei+ 16765 4.5 0.2 335372 44676 ? Sl 19:17 0:00 /snap/anbox/x1/usr/bin/anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity
root 16794 0.0 0.0 36776 3692 ? Ss 19:17 0:00 /snap/anbox/current/libexec/lxc/lxc-monitord /var/snap/anbox/common/containers 14
hanpfei+ 16917 0.0 0.2 1281208 42556 ? Sl 19:18 0:00 /snap/anbox/x1/usr/bin/anbox session-manager
root 16931 0.0 0.0 576280 8216 ? Ss 19:18 0:00 [lxc monitor] /var/snap/anbox/common/containers default
100000 16940 0.0 0.0 7920 2540 ? Ss 19:18 0:00 /system/bin/sh /anbox-init.sh
100000 16999 0.0 0.0 16472 4068 ? Sl 19:18 0:00 /system/bin/anboxd
hanpfei+ 17087 0.0 0.0 19300 936 pts/2 R+ 19:18 0:00 grep --color=auto anbox
$ adb devices
List of devices attached
emulator-5558 device
$ lsof -i | grep adb
adb 30288 hanpfei0306 6u IPv4 23788668 0t0 TCP localhost:5037 (LISTEN)
adb 30288 hanpfei0306 7u IPv4 27391368 0t0 TCP localhost:42048->localhost:5559 (ESTABLISHED)
$ lsof -i | grep 42048
anbox 16917 hanpfei0306 29u IPv4 27385836 0t0 TCP localhost:5559->localhost:42048 (ESTABLISHED)
adb 30288 hanpfei0306 7u IPv4 27391368 0t0 TCP localhost:42048->localhost:5559 (ESTABLISHED)
此時(shí)可以通過 adb
命令查看 Anbox 起動(dòng)的 Android 系統(tǒng)的狀況做修,如下面這樣:
$ adb devices
List of devices attached
emulator-5558 device
$ adb logcat
--------- beginning of system
12-01 01:57:25.245 16 16 I vold : Vold 3.0 (the awakening) firing up
12-01 01:57:25.245 16 16 V vold : Detected support for: ext4 vfat
12-01 01:57:25.260 16 16 E vold : Failed to open default fstab /fstab.goldfish: Operation not permitted
12-01 01:57:25.260 16 16 E vold : Error reading configuration... continuing anyways: Operation not permitted
12-01 01:57:25.264 16 25 D vold : e4crypt_init_user0
12-01 01:57:25.264 16 25 D vold : e4crypt_prepare_user_storage for volume null, user 0, serial 0, flags 1
12-01 01:57:25.264 16 25 D vold : Preparing: /data/system/users/0
12-01 01:57:25.264 16 25 D vold : Preparing: /data/misc/profiles/cur/0
12-01 01:57:25.264 16 25 D vold : Preparing: /data/misc/profiles/cur/0/foreign-dex
12-01 01:57:25.264 16 25 D vold : Preparing: /data/system_de/0
12-01 01:57:25.264 16 25 D vold : Preparing: /data/misc_de/0
12-01 01:57:25.264 16 25 D vold : Preparing: /data/user_de/0
當(dāng) Anbox 起動(dòng)的 Android 系統(tǒng)內(nèi)所需的應(yīng)用程序都啟動(dòng)完畢時(shí)霍狰,通過 Anbox 應(yīng)用將可以看到 Android 系統(tǒng)的桌面,可以看到 Android 系統(tǒng)中的應(yīng)用饰及,如下圖:
Anbox 項(xiàng)目寫了一個(gè)名為 org.anbox.appmgr
的 Java 應(yīng)用程序蔗坯,用以替代原始 Android 系統(tǒng)中的 Launcher,以展示已安裝應(yīng)用列表旋炒。隨后就可以像操作普通的桌面 Linux 系統(tǒng)中的應(yīng)用那樣操作 Android 內(nèi)的應(yīng)用了步悠。
此時(shí),查看主機(jī) Linux 系統(tǒng)中與 Anbox 有關(guān)的進(jìn)程瘫镇,可以看到如下這些:
$ ps -aux | grep anbox
root 30438 0.0 0.0 373372 12144 ? Ssl 09:55 0:00 /snap/anbox/65/usr/bin/anbox container-manager --data-path=/var/snap/anbox/common/ --android-image=/snap/anbox/65/android.img --daemon
hanpfei+ 30630 0.6 1.7 2770120 280580 ? Sl 09:57 0:07 /snap/anbox/65/usr/bin/anbox session-manager
root 30644 0.0 0.0 379672 8016 ? Ss 09:57 0:00 [lxc monitor] /var/snap/anbox/common/containers default
100000 30652 0.0 0.0 7920 6516 ? Ss 09:57 0:00 /system/bin/sh /anbox-init.sh
100000 30711 0.0 0.0 16728 9240 ? Sl 09:57 0:00 /system/bin/anboxd
110000 31209 0.0 0.7 1074676 116412 ? Sl 09:57 0:00 org.anbox.appmgr
進(jìn)程號(hào)為 30438 和 30644 的兩個(gè)進(jìn)程組成了容器管理器服務(wù)鼎兽。進(jìn)程號(hào)為 30630 的進(jìn)程為我們啟動(dòng)的 Anbox 應(yīng)用。進(jìn)程號(hào)為 30652铣除,30711谚咬,和 31209 的幾個(gè)進(jìn)程,實(shí)際為 Anbox 啟動(dòng)的容器中運(yùn)行的 Android 系統(tǒng)的進(jìn)程尚粘。Anbox 的整體設(shè)計(jì)可以參考 Anbox 一文择卦。
Anbox snap
Anbox 應(yīng)用通過 snap 方式打包,下載 anbox 的源碼郎嫁,并在源碼目錄下執(zhí)行 snapcraft秉继,可以生成 anbox 的 .snap 文件:
$ mkdir android-images
$ cp /path/to/android.img android-images/android.img
$ snapcraft
生成的 .snap 文件還可以通過如下命令進(jìn)行安裝:
$ snap install --dangerous --devmode anbox_3-7266fe2_amd64.snap
通過 Anbox 的 snapcraft.yaml
文件,可以對(duì) Anbox 運(yùn)行時(shí)泽铛、命令和服務(wù)有更深入的了解尚辑。Anbox 的 snapcraft.yaml
文件長(zhǎng)這樣:
name: anbox
version: 3
version-script: |
if [ "$SNAPCRAFT_GRADE" = "stable" ]; then
echo $SNAPCRAFT_PROJECT_VERSION
else
echo $SNAPCRAFT_PROJECT_VERSION-$(git rev-parse --short HEAD)
fi
summary: Android in a Box
description: |
Runtime for Android applications which runs a full Android system
in a container using Linux namespaces (user, ipc, net, mount) to
separate the Android system fully from the host.
confinement: devmode
grade: devel
slots:
# Depending on in which environment we're running we either need
# to use the system or session DBus so we also need to have one
# slot for each.
dbus-session:
interface: dbus
bus: system
name: org.anbox
dbus-system:
interface: dbus
bus: system
name: org.anbox
apps:
anbox:
command: bin/anbox-wrapper.sh
container-manager:
command: bin/container-manager.sh start
stop-command: bin/container-manager.sh stop
daemon: simple
collect-bug-info:
command: bin/collect-bug-info.sh
parts:
android-images:
plugin: dump
# This needs to be any directory but not the root one as if we use
# it we get superious permissions errors with the copied .git tree
source: data
build-packages:
- wget
install: |
LOCAL_IMAGE=$SNAPCRAFT_PART_INSTALL/../../../android-images/android.img
if [ -f $LOCAL_IMAGE ]; then
echo "Using local image $LOCAL_IMAGE"
cp $LOCAL_IMAGE $SNAPCRAFT_PART_INSTALL/android.img
else
IMAGE_PATH=
IMAGE_NAME=
ARCH=$(uname -m)
case "$ARCH" in
x86_64)
IMAGE_PATH="2017/07/13"
IMAGE_NAME="android_3_amd64.img"
;;
arm*)
IMAGE_PATH="2017/06/12"
IMAGE_NAME="android_1_armhf.img"
;;
*)
echo "ERROR: Unknown architecture $ARCH"
exit 1
;;
esac
# FIXME: downloading with a source: field doesn't work as snapcraft
# expects the downloaded file to be an archive it can extract.
echo "Downloading image..."
wget http://build.anbox.io/android-images/$IMAGE_PATH/$IMAGE_NAME
mv $IMAGE_NAME $SNAPCRAFT_PART_INSTALL/android.img
fi
prime:
- android.img
anbox-common:
plugin: dump
source: scripts
organize:
snap-wrapper.sh: bin/anbox-wrapper.sh
container-manager.sh: bin/container-manager.sh
anbox-bridge.sh: bin/anbox-bridge.sh
collect-bug-info.sh: bin/collect-bug-info.sh
prime:
- bin/anbox-bridge.sh
- bin/anbox-wrapper.sh
- bin/container-manager.sh
- bin/collect-bug-info.sh
apparmor:
plugin: nil
stage-packages:
- apparmor
lxc:
source: https://github.com/lxc/lxc
source-type: git
source-tag: lxc-2.0.7
build-packages:
- libapparmor-dev
- libcap-dev
- libgnutls28-dev
- libseccomp-dev
- pkg-config
plugin: autotools
configflags:
- --disable-selinux
- --disable-python
- --disable-lua
- --disable-tests
- --disable-examples
- --disable-doc
- --disable-api-docs
- --disable-bash
- --disable-cgmanager
- --disable-apparmor
- --disable-seccomp
- --enable-capabilities
- --with-rootfs-path=/var/snap/anbox/common/lxc/
- --libexecdir=/snap/anbox/current/libexec/
organize:
snap/anbox/current/libexec: libexec
prime:
- lib/liblxc.so.1
- lib/liblxc.so.1.2.0
- libexec/lxc/lxc-monitord
- bin/lxc-start
- bin/lxc-stop
- bin/lxc-info
- bin/lxc-attach
- bin/lxc-ls
- bin/lxc-top
anbox:
plugin: cmake
after:
- lxc
source: .
configflags:
# FIXME: Anbox currently has some paths with hard coded prefixes. Once
# that is fixed we can avoid using a prefix here.
- -DCMAKE_INSTALL_PREFIX:PATH=/usr
- -DANBOX_VERSION=$SNAPCRAFT_PROJECT_VERSION
build-packages:
- build-essential
- cmake
- cmake-data
- cmake-extras
- debhelper
- dbus
- google-mock
- libboost-dev
- libboost-filesystem-dev
- libboost-log-dev
- libboost-iostreams-dev
- libboost-program-options-dev
- libboost-system-dev
- libboost-test-dev
- libboost-thread-dev
- libcap-dev
- libdbus-1-dev
- libdbus-cpp-dev
- libegl1-mesa-dev
- libgles2-mesa-dev
- libglib2.0-dev
- libglm-dev
- libgtest-dev
- libprotobuf-dev
- libproperties-cpp-dev
- libsdl2-dev
- libsdl2-image-dev
- pkg-config
- protobuf-compiler
stage-packages:
- libegl1-mesa
- libgles2-mesa
- libgl1-mesa-glx
- libsdl2-2.0-0
- libsdl2-gfx-1.0-0
install: |
make test
prime:
- usr/bin/anbox
- usr/share/anbox
- usr/lib/*-linux-*/
從 Anbox 的 snapcraft.yaml
文件中可以看到,Anbox snap 安裝的幾個(gè)命令和服務(wù)盔腔,是一些腳本:
apps:
anbox:
command: bin/anbox-wrapper.sh
container-manager:
command: bin/container-manager.sh start
stop-command: bin/container-manager.sh stop
daemon: simple
collect-bug-info:
command: bin/collect-bug-info.sh
Anbox snap 主要由這幾部分組成:
- Android 系統(tǒng)鏡像杠茬,先找本地的
android-images/android.img
月褥,如果找不到,就根據(jù)主機(jī)系統(tǒng)的 CPU 架構(gòu)瓢喉,從遠(yuǎn)端下載 - anbox-common宁赤,主要是一些腳本,提供 Anbox snap 的命令和服務(wù)栓票,由
source:
行可以看到這些腳本都位于源碼目錄的scripts
子目錄下 - apparmor决左,從 Ubuntu 的 APT 源獲得
- lxc,用于做容器管理逗载,從 GitHub 獲得源碼哆窿,并由 tag 為 lxc-2.0.7 的版本編譯生成
- anbox 二進(jìn)制可執(zhí)行程序链烈,通過 cmake 編譯生成厉斟,如:
$ git clone https://github.com/anbox/anbox.git
$ cd anbox
$ mkdir build
$ cd build
$ cmake ..
$ make
還可以通過如下命令編譯帶符號(hào)的 Debug 版 anbox 二進(jìn)制可執(zhí)行程序:
$ mkdir Debug
$ cd Debug
$ cmake -DCMAKE_BUILD_TYPE=Debug ..
$ make
或 Release 版:
$ mkdir Release
$ cd Release
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make
這里來看一下 Anbox snap 的主要命令和服務(wù),也就是幾個(gè)腳本的實(shí)現(xiàn)强衡。container-manager.sh
腳本擦秽,用于起動(dòng)容器管理服務(wù),其內(nèi)容如下:
#!/bin/sh
set -x
# We need to put the rootfs somewhere where we can modify some
# parts of the content on first boot (namely file permissions).
# Other than that nothing should ever modify the content of the
# rootfs.
DATA_PATH=$SNAP_COMMON/
ROOTFS_PATH=$DATA_PATH/rootfs
ANDROID_IMG=$SNAP/android.img
if [ ! -e $ANDROID_IMG ]; then
echo "ERROR: android image does not exist"
exit 1
fi
start() {
# Make sure our setup path for the container rootfs
# is present as lxc is statically configured for
# this path.
mkdir -p $SNAP_COMMON/lxc
# We start the bridge here as long as a oneshot service unit is not
# possible. See snapcraft.yaml for further details.
$SNAP/bin/anbox-bridge.sh start
# Ensure FUSE support for user namespaces is enabled
echo Y | tee /sys/module/fuse/parameters/userns_mounts || echo "WARNING: kernel doesn't support fuse in user namespaces"
# Only try to use AppArmor when the kernel has support for it
AA_EXEC="$SNAP/usr/sbin/aa-exec -p unconfined --"
if [ ! -d /sys/kernel/security/apparmor ]; then
echo "WARNING: AppArmor support is not available!"
AA_EXEC=""
fi
exec $AA_EXEC $SNAP/bin/anbox-wrapper.sh container-manager \
--data-path=$DATA_PATH \
--android-image=$ANDROID_IMG \
--daemon
}
stop() {
$SNAP/bin/anbox-bridge.sh stop
}
case "$1" in
start)
start
;;
stop)
stop
;;
*)
echo "ERROR: Unknown command '$1'"
exit 1
;;
esac
在這個(gè)腳本中漩勤,啟動(dòng)容器管理服務(wù)時(shí)感挥,調(diào)用 anbox-bridge.sh start
腳本為 Anbox 創(chuàng)建虛擬網(wǎng)卡,并調(diào)用 anbox-wrapper.sh
啟動(dòng) anbox 二進(jìn)制可執(zhí)行程序越败。腳本的執(zhí)行依賴幾個(gè)環(huán)境變量的設(shè)置触幼。在腳本執(zhí)行時(shí),環(huán)境變量 SNAP
指向 /snap/anbox/current
究飞,環(huán)境變量 SNAP_COMMON
指向 /var/snap/anbox/common
置谦。
anbox-wrapper.sh
也就是 anbox 源碼庫(kù)中的 scripts/snap-wrapper.sh
,其內(nèi)容如下:
#!/bin/bash
if [ "$SNAP_ARCH" == "amd64" ]; then
ARCH="x86_64-linux-gnu"
elif [ "$SNAP_ARCH" == "armhf" ]; then
ARCH="arm-linux-gnueabihf"
else
ARCH="$SNAP_ARCH-linux-gnu"
fi
export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH:$LD_LIBRARY_PATH
# Mesa Libs
export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/mesa:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$SNAP/usr/lib/$ARCH/mesa-egl:$LD_LIBRARY_PATH
# XDG Config
export XDG_CONFIG_DIRS=$SNAP/etc/xdg:$XDG_CONFIG_DIRS
export XDG_CONFIG_DIRS=$SNAP/usr/xdg:$XDG_CONFIG_DIRS
# Note: this doesn't seem to work, QML's LocalStorage either ignores
# or fails to use $SNAP_USER_DATA if defined here
export XDG_DATA_DIRS=$SNAP_USER_DATA:$XDG_DATA_DIRS
export XDG_DATA_DIRS=$SNAP/usr/share:$XDG_DATA_DIRS
# Tell libGL where to find the drivers
export LIBGL_DRIVERS_PATH=$SNAP/usr/lib/$ARCH/dri
# ensure the snappy gl libs win
export LD_LIBRARY_PATH="$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH"
# Workaround in snapd for proprietary nVidia drivers mounts the drivers in
# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH
# Without that OpenGL using apps do not work with the nVidia drivers.
# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/lib/snapd/lib/gl
# We set XDG_DATA_HOME to SNAP_USER_COMMON here as this will be the location we will
# create all our application launchers in. The system application launcher will
# be configured by our installer to look into this directory for available
# launchers.
export XDG_DATA_HOME="$SNAP_USER_COMMON/app-data"
exec $SNAP/usr/bin/anbox $@
在這個(gè)腳本中亿傅,主要導(dǎo)出了一些環(huán)境變量媒峡,LD_LIBRARY_PATH
,XDG_CONFIG_DIRS
葵擎,XDG_DATA_DIRS
谅阿,LIBGL_DRIVERS_PATH
和 XDG_DATA_HOME
,以使 anbox 二進(jìn)制可執(zhí)行程序在啟動(dòng)之后酬滤,可以找到所需的動(dòng)態(tài)鏈接庫(kù)等签餐。
打賞
參考文檔:
Upstart
淺析 Linux 初始化 init 系統(tǒng),Systemd
Debug vs Release in CMAKE