Nokia N900 >> Easy Debian

分析Easy Debain(CLI)


在Easy Debian的強大加持下,N900幾乎就像是一台掌上型電腦,加上N900本身就是一台手機,真可以說是集完美於一身,可以當手機又可以當電腦使用。Easy Debian本身就是由一堆Linux Shell Script組成的程式,主要功能就是做mount和chroot的動作,如果搭配的Image有安裝Display Server,如:Xephyr,這樣就可以同時運行Maemo和其它Linux Distribution,如:Debian、Ubuntu或Arch Linux,加上N900本身是搭配電阻觸控,不像目前Android手機搭配的都是電容觸控,因為,目前Linux Distribution都還是以滑鼠為主要操作介面,因此,電阻觸控在這方面的操作會比電容觸控更適合。

Easy Debian(CLI)的整個執行過程如下:
首先確定一開始的執行命令

$ cat /usr/share/applications/hildon/debchroot.desktop 
  [Desktop Entry]
  Encoding=UTF-8
  Name=Debian chroot
  GenericName=Debian Terminal Window
  Exec=osso-xterm "sudo debian"
  Icon=debian-logo
  X-Osso-Type=application/x-executable
  X-HildonDesk-ShowInToolbar=true
  Terminal=true
  Type=Application
  StartupNotify=true

入口命令是sudo debian,而debian本身就是一個Linux Shell Script檔案,該檔案位於/sbin/debian

#!/bin/sh
# Sets up (if necessary) for chroot into a Debian environment.
# Expects root privileges, does not drop them. 
# Look to /usr/bin/debbie for a friendly wrapper.

# By Alan M Bruce (qole) with help from Benson Mitchell and Thomas Perl
#
# GPL licensed; keep code free!

if [ "`whoami`" != "root" ] ; then
  echo "please run me as root!"
  exit 9
fi

#Pull in the config, if possible...
if [ -f "/home/user/.chroot" ] ; then

. /home/user/.chroot

else
  echo "No ~/.chroot file." >/dev/stderr
fi

#This comes from the config file... If not, fall back on '/debian'
if [ "x$CHROOT" = "x" ] ; then
  CHROOT=/.debian
  echo "No chroot dir specified; using $CHROOT" >/dev/stderr
else
  echo "Chroot dir specified: $CHROOT" >/dev/stderr
fi

#This comes from the config. If not, search for debian*.img.ext2
if [ "x$IMGFILE" = "x" ] ; then
  echo "No image file or partition specified." >/dev/stderr
  IMGMMC="`ls -1 /home/user/MyDocs/debian*.img* /media/mmc1/debian*.img* | head -1`"
  if [ "x$IMGMMC" != x ] ; then
    IMGFILE="$IMGMMC"
  else
    MSG1=`printf "ERROR!\n\nYou have no debian.img.ext2 file on your memory cards.\n\nPlease use the Debian Image Installer in Extras."`
    if [ ! -f "/usr/bin/gxmessage" ] ; then
      echo $MSG1 >/dev/stderr
    else
      gxmessage -center -alignbuttons center -buttons GTK_STOCK_OK:0 -geometry 680x250 -title "MISSING DISK IMAGE" "$MSG1"
    fi
    exit 9
  fi
else
  echo "$IMGFILE specified in ~/.chroot" >/dev/stderr
fi

#
#Make the temp dir bigger for OpenOffice etc.
#
#This comes from the config file... 
#If not, fall back to a 6MB /tmp dir
#

[ "x$TMPSIZE" != x ] || TMPSIZE=6M
mount -o remount,size=$TMPSIZE /tmp

#Messy hack to make tap-and-hold work with GTK apps.
export GTK_MODULES=libgtkstylus.so

#Some OpenOffice environment variables
export SAL_USE_VCLPLUGIN="gtk"
export OOO_FORCE_DESKTOP="gnome"
export SAL_NOOPENGL="true"
export OOO_DISABLE_RECOVERY="true"
export SAL_DISABLE_SYNCHRONOUS_PRINTER_DETECTION="true"
#export SAL_DISABLE_CUPS="true"

qchroot $IMGFILE $CHROOT "$@"
行數 程式說明
18 取得變數名稱,如:IMGFILE、CHROOT等名稱
25~30 判斷CHROOT是否定義在.chroot裡,假如沒有,則使用/.debian取代,比較特別的地方在於[ "x$CHROOT" = "x" ]語法,這個語法用來判斷"x" + "$CHROOT"是否等於"x",如果等於,代表$CHROOT沒有定義。
33~49 判斷IMGFILE是否定義,如果沒有,則捜尋MyDocs或mmc1裡面,是否有debian*.img的檔案,至於gxmessage命令,它是一個顯示Message Box的命令。
58~59 mount /tmp資料夾。
62~69 export相關變數,export的做用就類似set的用意。
72 執行qchroot並代入參數($@代表其餘參數依序傳入),qchroot是另一個Linux Shell Script檔案。

qchroot檔案位於/sbin/qchroot,內容如下

#!/bin/sh
# Sets up (if necessary) and chroots into a different environment.
# Expects root privileges, does not drop them. 

# By Alan M Bruce (qole) with help from Benson Mitchell and Thomas Perl
#
# GPL licensed; keep code free!

# This script should have a wrapper to set up extra variables,
# OR, it can be run as a command:
# qchroot <part/file/'none'> <chroot dir> <command> <params...>

if [ "`whoami`" != "root" ] ; then
  echo "please run me as root!"
  exit 9
fi

IMGFILE=$1
shift 1

CHROOT=$1
shift 1

# echo qchroot $IMGFILE $CHROOT $*

# Strip off a trailing slash
LASTCHAR=`echo $CHROOT | cut -c ${#CHROOT}`
if [ "$LASTCHAR" = "/" ] ; then
   echo "..stripping trailing slash..." >/dev/stderr
   CHROOT=`echo $CHROOT | cut -c 0-$((${#CHROOT}-1))`
fi

# if the user supplies "none" for the image file,
# skip the qmount step. Thanks for reporting, Fabry!

if [ "$IMGFILE" != "none" ] ; then
  qmount $IMGFILE $CHROOT
  MOUNTSUCCESS=$?
else
  MOUNTSUCCESS=0
fi

if [ "$MOUNTSUCCESS" != "1" ] && [ "$MOUNTSUCCESS" != "0" ] ; then
  echo Cancelling chroot...
  exit $MOUNTSUCCESS
fi

if [ "$MOUNTSUCCESS" = "0" ] ; then
  #Make the tablet's devices available to the chroot
  echo . >/dev/stderr
  mount -o bind /dev "$CHROOT/dev"
  mount -o bind /proc "$CHROOT/proc"

  #Gentoo wiki says this will make X work
  echo .. >/dev/stderr
  mount -t devpts none "$CHROOT/dev/pts"
  mount -o bind /tmp "$CHROOT/tmp"

  #Open e-mail attachments, etc
  mount -o bind /var/tmp "$CHROOT/var/tmp"

  #ArchLinux suggestions
  mount -o bind /dev/shm "$CHROOT/dev/shm"
  mount -o bind /sys "$CHROOT/sys"

  #Any external devices
  echo ... >/dev/stderr
  MNTD=`cat /proc/mounts | grep ' /media/' | awk '{print $2}'`

  for MDRV in $MNTD ; do
    if [ ! -d "$CHROOT$MDRV" ] ; then
      mkdir -p "$CHROOT$MDRV"
    fi
    mount -o bind "$MDRV" "$CHROOT$MDRV"
  done

  #Mount the user's home dir
  echo .... >/dev/stderr
  #mount -o bind /home/user "$CHROOT/home/user"

  # Do it the Fremantle way.
  mount /dev/mmcblk0p2 "$CHROOT/home"
  mount /dev/mmcblk0p1 "$CHROOT/home/user/MyDocs"
  
  #Make DBus work
  mount -o bind /var/run/dbus "$CHROOT/var/run/dbus"
  mount -o bind /var/lib/dbus "$CHROOT/var/lib/dbus"

  #Make pulseaudio work
  mount -o bind /var/run/pulse "$CHROOT/var/run/pulse"

  #Speed hacks: lower the priority of processes
  #renice 0 `pidof mmcqd`
  #renice 20 `pidof trackerd`

  # Sync the chroot if requested...
  if [ -f /home/user/.synchroot ] ; then 
    /sbin/synchroot $CHROOT
    rm /home/user/.synchroot
  fi

  # Place any commands you wish to run the first time you chroot
  # into the /var/run/onfirstchroot-ext.rc file (inside your rootfs)

  if [ -f "$CHROOT/var/run/onfirstchroot-ext.rc" ] ; then
    . "$CHROOT/var/run/onfirstchroot-ext.rc"
  fi

  # Place any commands you wish to run from inside the chroot 
  # the first time you chroot into the /var/run/onfirstchroot.rc
  # file (inside your rootfs)

  if [ -f "$CHROOT/var/run/onfirstchroot.rc" ] ; then
    chroot $CHROOT "/var/run/onfirstchroot.rc"
  fi

fi

# Place any commands you wish to run every time you chroot
# into the /var/run/onchroot-ext.rc file (inside your rootfs)

if [ -f "$CHROOT/var/run/onchroot-ext.rc" ] ; then
  . "$CHROOT/var/run/onchroot-ext.rc"
fi

# Place any commands you wish to run from inside the chroot
# every time you chroot into the /var/run/onchroot.rc
# file (inside your rootfs)

if [ -f "$CHROOT/var/run/onchroot.rc" ] ; then
  chroot $CHROOT "/var/run/onchroot.rc"
fi

#All set up. Set flag for next time...

if [ ! -d "$CHROOT/var/lock" ] ; then
  mkdir -p "$CHROOT/var/lock"
fi

trap "rm -f $CHROOT/var/lock/chroot-complete ; echo -ne '\033]0;X Terminal\007'>/dev/stderr ; exit" INT TERM EXIT
echo $IMGFILE $@ > "$CHROOT/var/lock/chroot-complete"

#Custom prompt and xterm title. Reduces confusion.
CHRLABEL=`blkid -s LABEL $IMGFILE | cut -d' ' -f2 | cut -d'=' -f2 | sed 's/"//g'`

#If the file is mounted on loop, use that label.
if [ "x$CHRLABEL" = "x" ] ; then

  # first find the loop
  LOOPNO=`mount | grep loop | grep $CHROOT | awk '{print $1}'`

  if [ "x$LOOPNO" != "x" ] ; then
     CHRLABEL=`blkid -s LABEL $LOOPNO | cut -d' ' -f2 | cut -d'=' -f2 | sed 's/"//g'`
  fi
fi

if [ "x$CHRLABEL" = "x" ] ; then
  CHRLABEL=chroot
fi

echo -ne "\033]0;$CHRLABEL\007" >/dev/stderr
export PS1="[\u@$CHRLABEL: \w]"

#Actually chroot
echo "Everything set up, running chroot..." >/dev/stderr
chroot $CHROOT "$@"

#All done, reset.
exit 0
行數 程式說明
18~19 將第一個參數指到IMGFILE,接著移掉第一個參數
21~22 將第一個參數(原本的第二個參數)指到CHROOT,接著移掉第一個參數
28~31 剔除反斜線"/"
36~41 執行qmount程式並將結果($?)存到MOUNTSUCCESS,qmount是另一個Linux Shell Script檔案
50~64 mount系統資源
67~75 mount /media底下的資料夾
82 mount mmcblk0p2(/home)
83 mount mmcblk0p1(MyDocs)
86~90 mount dbus & pulseaudio資源
97~100 sync .synchroot
105~107

qmount程式位於/sbin/qmount,內容如下

#!/bin/sh
# Sets up (if necessary) and chroots into a different environment.
# Expects root privileges, does not drop them. 

# By Alan M Bruce (qole) with help from Benson Mitchell and Thomas Perl
#
# GPL licensed; keep code free!

# Hacked roughly to work with Fremantle. Help always appreciated. I can be found on talk.maemo.org.

# This script should have a wrapper to set up extra variables,
# OR, it can be run as a command:
# qmount <partition/file/'none'> <mountpoint>

if [ "`whoami`" != "root" ] ; then
  echo "please run me as root!"
  exit 9
fi

IMGFILE=$1
MNTPT=$2

# echo qmount $IMGFILE $MNTPT

#Ensure that we have an image or partition to mount

if [ ! -f "$IMGFILE" ] && [ ! -b "$IMGFILE" ] ; then
  MSG1=`printf "ERROR!\n\nThe image specified ($IMGFILE) does not exist or is neither\na regular nor a block special file.\n\nFirst parameter must be an image file or partition"`
  if [ ! -f "/usr/bin/gxmessage" ] ; then
    echo $MSG1 >/dev/stderr
  else
    gxmessage -center -alignbuttons center -buttons GTK_STOCK_OK:0 -geometry 680x250 -title "EZ-CHROOT ERROR" "$MSG1"
  fi
  exit 9
fi

#Ensure that we have a chroot directory to mount the image or partition on

if [ "x$MNTPT" = "x" ] || [ "x`echo $MNTPT | grep '/'`" = "x"  ] ; then
  MSG1=`printf "ERROR!\n\nNo chroot directory specified!\n\nSecond parameter must be chroot dir (eg. /debian)"`
  if [ ! -f "/usr/bin/gxmessage" ] ; then
    echo $MSG1 >/dev/stderr
  else
    gxmessage -center -alignbuttons center -buttons GTK_STOCK_OK:0 -geometry 680x250 -title "EZ-CHROOT ERROR" "$MSG1"
  fi
  exit 9
fi

# Strip off a trailing slash
LASTCHAR=`echo $MNTPT | cut -c ${#MNTPT}`
if [ "$LASTCHAR" = "/" ] ; then
   echo "..stripping trailing slash..." >/dev/stderr
   MNTPT=`echo $MNTPT | cut -c 0-$((${#MNTPT}-1))`
fi

#Check to see if already mounted
if [ -f "$MNTPT/var/lock/qmount-complete" ] ; then
  echo "$MNTPT has a qmount already!" >/dev/stderr
  MTDIMGFILE=`cat $MNTPT/var/lock/qmount-complete`
  if [ "$IMGFILE" != "$MTDIMGFILE" ] ; then
    echo $MTDIMGFILE already mounted here! >/dev/stderr
    MSG1=`printf "Mount problem!\n\n$MTDIMGFILE already mounted on $MNTPT"`
       if [ ! -f "/usr/bin/gxmessage" ] ; then
         echo $MSG1 >/dev/stderr
       else
         gxmessage -center -alignbuttons center -buttons GTK_STOCK_OK:0 -geometry 680x250 -title "EZ-CHROOT ERROR" "$MSG1"
       fi
    exit 9
    # Instead of failing, we could unmount instead...
    # echo Unmounting...
    # closechroot $MNTPT
  else
    echo $MTDIMGFILE already mounted on $MNTPT... >/dev/stderr
    exit 1
  fi
fi 

if [ ! -f "$MNTPT/var/lock/qmount-complete" ] ; then
 echo "Mounting..."
 if [ "$IMGFILE" != "none" ] ; then

   if [ -f "$IMGFILE" ] ; then
     LOOP=loop,
     echo "using image file: $IMGFILE" >/dev/stderr
     if [ "x$IMGFS" = x ] ; then
       IMGFS=`echo $IMGFILE | awk -F '.' '{print $NF}'`
       echo "fs type is $IMGFS" >/dev/stderr
     fi
   else
     LOOP=
     echo "using device: $IMGFILE" >/dev/stderr
     PARTINFO="`blkid -s TYPE $IMGFILE`"
     if [ "x$IMGFS" = x ] ; then
       IMGFS=`echo $PARTINFO | awk '{print $NF}' | awk -F '=' '{print $NF}' | sed s/\"//g`
     fi
   fi

   # missing in Fremantle...
   # modprobe mbcache

   if [ "$IMGFS" != "ext4" ] && [ "$IMGFS" != "ext3" ] && [ "$IMGFS" != "ext2" ] ; then
     echo "Don't know $IMGFS: Using ext2 file system" >/dev/stderr
     IMGFS=ext2
   fi

   echo "Using $IMGFS file system"
   if [ "$IMGFS" = ext3 ] || [ "$IMGFS" = ext4 ] ; then
     #insmod "$MODULEPATH/jbd.ko" 2>/dev/null
     modprobe jbd
   fi

   #insmod "$MODULEPATH/$IMGFS.ko" 2>/dev/null
   modprobe $IMGFS

   if [ -d "/lib/modules/`uname -r`" ] ; then
     MODULEPATH="/lib/modules/`uname -r`"
   else
     MODULEPATH=/lib/modules/2.6.28-omap1
   fi

   if [ "$LOOP" = "loop," ] ; then

   # Check for dm-loop kernel module and dmlosetup command. 
   # If found, then use dm-loop instead of regular loop.

     if [ -f "$MODULEPATH/dm-loop.ko" ] && [ -f "/sbin/dmlosetup" ]; then

       # use dm-loop

       echo "mounting $IMGFILE on the turbo-loop ;)"
       #insmod $MODULEPATH/dm-mod.ko 2>/dev/null
       modprobe dm-mod
       #insmod $MODULEPATH/dm-loop.ko 2>/dev/null
       modprobe dm-loop

       NEXTLOOP=`ls -l /dev/dm-* 2>/dev/null | tail -1 | awk '{print $NF}' | awk -F '-' '{print $NF+1}'`
       if [ "x$NEXTLOOP" = "x"  ] ; then
         NEXTLOOP=0
       fi

       DMLOMSG=`dmlosetup loop$NEXTLOOP "$IMGFILE" 2>&1`
       MNTMSG=`mount -t "$IMGFS" /dev/dm-$NEXTLOOP "$MNTPT" -o noatime,nobh,nodiratime 2>&1` 

     else

       # use "regular" loop

       echo "mounting $IMGFILE on loop" >/dev/stderr
       NEXTLOOP=`mount | grep loop | tail -1 | awk '{print $1}' | awk -F "/" '{print $3}' | cut -c 5-6 | awk '{print $0+1}'`
       if [ "x$NEXTLOOP" = "x"  ] ; then
         NEXTLOOP=0
       fi

       DMLOMSG=""
       MNTMSG=`mount -t "$IMGFS" "$IMGFILE" "$MNTPT" -o loop,noatime,nobh,nodiratime 2>&1` 

     fi

     if [ "$?" != 0 ] ; then
       MSG1=`printf "Mount failure!\n\n$IMGFILE failed to mount on loop$NEXTLOOP\n\n$DMLOMSG\n$MNTMSG"`
       if [ ! -f "/usr/bin/gxmessage" ] ; then
         echo $MSG1 >/dev/stderr
       else
         gxmessage -center -alignbuttons center -buttons GTK_STOCK_OK:0 -geometry 680x250 -title "EZ-CHROOT ERROR" "$MSG1"
       fi
       exit 2
     fi
     echo ...$IMGFILE mounted on loop$NEXTLOOP >/dev/stderr
   else
     echo "mounting device: $IMGFILE" >/dev/stderr
     if ! mount -t "$IMGFS" "$IMGFILE" "$MNTPT" -o ${LOOP}noatime,nobh,nodiratime ; then
       MSG1=`printf "Mount failure!\n\n$IMGFILE failed to mount on $MNTPT"`
       if [ ! -f "/usr/bin/gxmessage" ] ; then
         echo $MSG1 >/dev/stderr
       else
         gxmessage -center -alignbuttons center -buttons GTK_STOCK_OK:0 -geometry 680x250 -title "EZ-CHROOT ERROR" "$MSG1"
       fi
       exit 3
     fi

   fi

  else
    echo "Not mounting any filesystem, chroot is $MNTPT" >/dev/stderr
  fi 

#All set up. Set flag for next time...

 if [ ! -d "$MNTPT/var/lock" ] ; then
   mkdir -p "$MNTPT/var/lock"
 fi

 # Place any commands you wish to run the first time you mount
 # into the $MNTPT/var/run/onmount.rc file

  if [ -f "$MNTPT/var/run/onmount.rc" ] ; then
    . "$MNTPT/var/run/onmount.rc"
  fi

 echo $IMGFILE > "$MNTPT/var/lock/qmount-complete"
 exit 0

fi

exit 1
行數 程式說明
27~35 確認IMGFILE檔案以及分割表是否存在
39~47 確認掛載點是否存在
49~54 剔除"/"符號
56~76 確認是否已經掛載
82~96 找出檔案類型、分割表資訊
101~104 如果無法確認檔案類型,則使用ext2
106~185 掛載驅動程式和檔案
189~191 利用資料夾當做旗標


返回上一頁