基本上 Emulator /system 目錄是唯讀的,要解除其唯讀屬性可以透過下列方法:

adb remount
adb push libmy.so /system/lib

但是,在 Android 2.0 (Eclair) 以後,上面的作法會出現這樣的錯誤:
failed to copy 'hosts' to '/system/etc/hosts': No space left on device

failed to copy 'hosts' to '/system/etc/hosts': Out of memory

解決方法是,開啟模擬器時不要直接從 AVD Manager介面開,請下指令:
emulator -avd youravdname -partition-size 128
接著再對這個模擬器使用上面的方法就不會出現錯誤了。

深究其原因是 partition size 預設是 64MB。從 adb shell 用 df 指令觀察的結果,/system 在2.x 的 image mount 之後剩下空間是 0K。因此即使 remount 之後也無法寫入。

Filesystem           1k-blocks      Used Available Use% Mounted on
tmpfs                   128276         0    128276   0% /dev
tmpfs                   128276         0    128276   0% /mnt/asec
/dev/block/mtdblock0     77568     77568         0 100% /system
/dev/block/mtdblock1    129152     54988     74164  43% /data
/dev/block/mtdblock2     65536      1156     64380   2% /cache
/dev/block/vold/179:0
                       1044472     65608    978864   6% /mnt/sdcard
/dev/block/vold/179:0
                       1044472     65608    978864   6% /mnt/secure/asec

可惜AVD Manager 沒地方可以設定 partition size。所以目前只能在 console 以手動下指定開emulator囉。

有用過 Android adb shell 的人應該都知道這個 shell 的功能實在是食之無味棄之可惜的雞肋,一些常用的 linux command 幾乎都不支援,所以今天要介紹 busybox 這個工具,它的支援相當豐富,以下是執行的畫面:

$ busybox
BusyBox v1.16.0 (2010-01-27 20:00:00 CET) multi-call binary.
Copyright (C) 1998-2009 Erik Andersen, Rob Landley, Denys Vlasenko
and others. Licensed under GPLv2.
See source distribution for full notice.

Usage: busybox [function] [arguments]...
   or: function [arguments]...

 BusyBox is a multi-call binary that combines many common Unix
 utilities into a single executable.  Most people will create a
 link to busybox for each function they wish to use and BusyBox
 will act like whatever it was invoked as.

Currently defined functions:
 [, [[, acpid, addgroup, adduser, adjtimex, ar, arp, arping, ash, awk,
 basename, beep, blkid, brctl, bunzip2, bzcat, bzip2, cal, cat, catv,
 chat, chattr, chgrp, chmod, chown, chpasswd, chpst, chroot, chrt, chvt,
 cksum, clear, cmp, comm, cp, cpio, crond, crontab, cryptpw, cttyhack,
 cut, date, dc, dd, deallocvt, delgroup, deluser, depmod, devmem, df,
 dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname, dos2unix, du,
 dumpkmap, dumpleases, echo, ed, egrep, eject, env, envdir, envuidgid,
 ether-wake, expand, expr, fakeidentd, false, fbset, fbsplash, fdflush,
 fdformat, fdisk, fgrep, find, findfs, flash_eraseall, flash_lock,
 flash_unlock, flashcp, fold, free, freeramdisk, fsck, fsck.minix,
 fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, gunzip, gzip,
 halt, hd, hdparm, head, hexdump, hostid, hostname, httpd, hush,
 hwclock, id, ifconfig, ifdown, ifenslave, ifplugd, ifup, inetd, init,
 inotifyd, insmod, install, ionice, ip, ipaddr, ipcalc, ipcrm, ipcs,
 iplink, iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5,
 klogd, last, length, less, linux32, linux64, linuxrc, ln, loadfont,
 loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls,
 lsattr, lsmod, lspci, lsusb, lzmacat, lzop, lzopcat, makedevs,
 makemime, man, md5sum, mdev, mesg, microcom, mkdir, mkdosfs, mke2fs,
 mkfifo, mkfs.ext2, mkfs.minix, mkfs.vfat, mknod, mkpasswd, mkswap,
 mktemp, modprobe, more, mount, mountpoint, msh, mt, mv, nameif, nc,
 netstat, nice, nmeter, nohup, nslookup, ntpd, od, openvt, passwd,
 patch, pgrep, pidof, ping, ping6, pipe_progress, pivot_root, pkill,
 popmaildir, poweroff, printenv, printf, ps, pscan, pwd, raidautorun,
 rdate, rdev, readahead, readlink, readprofile, realpath, reboot,
 reformime, renice, reset, resize, rm, rmdir, rmmod, route, rpm,
 rpm2cpio, rtcwake, run-parts, runlevel, runsv, runsvdir, rx, script,
 scriptreplay, sed, sendmail, seq, setarch, setconsole, setfont,
 setkeycodes, setlogcons, setsid, setuidgid, sh, sha1sum, sha256sum,
 sha512sum, showkey, slattach, sleep, softlimit, sort, split,
 start-stop-daemon, stat, strings, stty, su, sulogin, sum, sv, svlogd,
 swapoff, swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar,
 taskset, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time,
 timeout, top, touch, tr, traceroute, traceroute6, true, tty, ttysize,
 tunctl, tune2fs, udhcpc, udhcpd, udpsvd, umount, uname, uncompress,
 unexpand, uniq, unix2dos, unlzma, unlzop, unzip, uptime, usleep,
 uudecode, uuencode, vconfig, vi, vlock, volname, wall, watch, watchdog,
 wc, wget, which, who, whoami, xargs, yes, zcat, zcip

網路上已經有人幫忙把 busybox comile 成 android 可以用的 binary 檔了,有需要的人可以到這裡下載。

安裝 busybox 的步驟如下:

1. 建立安裝的目錄
adb shell mkdir /data/busybox

2. 複製 busybox 的 binary 檔到前一個步驟所建立的目錄:
adb push busybox /data/busybox/busybox

3. 開始安裝 busybox
adb shell
cd /data/busybox
./busybox --install. 
然後你可以檢查 /data/busybox 目錄,裡面應該有許多links.
但是預設的路徑並沒有被指定到 /data/busybox 為了讓用起來方便一點,可以修改 init.rc 多加進去 busybox 的安裝路徑,但如果是在 emulator 上 run 那就要去修改 ramdisk.img 才能達到一勞永逸的效果,否則每次開啟 emulator 後 init.rc 會被覆蓋掉。

修改 ramdisk.img 的步驟:

2.6內核開始,initrd.img採用cpio壓縮,ramdisk.img也一樣,使用gunzip解壓縮,然後再使用 cpio解包。

1. 將 ramdisk.img 從 android sdk 的 platroms\android-xx 目錄下複製到 linux 的作業環境其他目錄(如果已經在 linux 下則此一步驟省略)

2. 名稱改為 ramdisk.img.gz 並用 gunzip 解壓
mv ramdisk.img ramdisk.img.gz
gunzip ramdisk.img.gz

3. 新建一個文件夾 ramdisk 並進入此目錄後用 cpio 解開
mkdir ramdisk
cd ramdisk
cpio -i -F ../ramdisk.img
此時現在目錄已經是解開後的 ramdisk 檔案目錄了

4. 修改 init.rc 在 PATH 中加上 /data/busybox 路徑
## Global environment setup
##
env {
#其中, /data/busybox 為busybox安裝路徑,bash也是放在其中
PATH /data/busybox:/sbin:/system/sbin:/system/bin
...
}

5. 重新打包 ramdisk
find . | cpio -o -H newc -O ../new_ramdisk.img
gzip ../new_ramdisk.img

6. 把 new_ramdisk.img.gz 改成 ramdisk.img 並複製到 emulator 原來放置 ramdisk.img 的目錄覆蓋掉。大功告成...^^