<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    每日一得

    不求多得,只求一得 about java,hibernate,spring,design,database,Ror,ruby,快速開發
    最近關心的內容:SSH,seam,flex,敏捷,TDD
    本站的官方站點是:顛覆軟件

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      220 隨筆 :: 9 文章 :: 421 評論 :: 0 Trackbacks
    key words: bash編程

    轉自 這里

    另一篇 詳解Bash命令行處理

    bash編程教學實例

    bash編程

    --------------------------------------------------------------------------------
    時間:2004/03/02    來源:不詳

      Shell Script(bash)簡介

      眾所皆知地,UNIX上以小工具著名,利用許多簡單的小工具,來完成原本需要大量軟體開發的工作,這一點特色,使得UNIX成為許多人心目中理想的系統平臺?!?br />   在眾多的小工具中,Shell Script算得上是最基本、最強大、運用最廣泛的一個。它運用圍之廣,不但從系統啟動、程式編譯、定期作業、上網連線,甚至安裝整個Linux系統,都可以用它來完成?!?br />
      因為Shell Script是利用您平日在使用的一些指令,將之組合起來,成為一個"程式"。如果您平日某些序列的指令下得特別頻繁,便可以將這些指令組合起來,成為另 一個新的指令。這樣,不但可以簡化并加速操作速度,甚至還可以干脆自動定期執行,大大簡化系統管理工作。 

      *************************
      Bash(GNU Bourne-Again SHell)是許多Linux平臺的內定Shell,事實上,還有許多傳統UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等, Shell Script大致都類同,當您學會一種Shell以后,其它的Shell會很快就上手,大多數的時候,一個Shell Script通常可以在很多種Shell上使用。 
      這里我介紹您bash的使用方法。事實上,當您"man bash"時,就可以看到bash的說明書,不過對許多人來說,這份說明書猶如"無字天書"一樣難懂。這份文件,主要資料來源為"man bash",我加上一些實際日常的應用例來說明。希望這樣能讓那些始終不得其門而入的人們,多多少少能有點概念。 


      教學例子

      "Hello world" Shell Script 
      照傳統程式教學例,這一節介紹Shell Script的"Hello World"如何撰寫。 

      *************************

      #!/bin/sh 
      # Filename : hello 
      echo "Hello world!" 

      *************************

      大家應該會注意到第一行的"#!/bin/sh"。在UNIX下,所有的可執行Script,不管是那一種語言,其開頭都是"#!",例如Perl是 "#!/usr/bin/perl",tcl/tk是"#!/usr/bin/wish",看您要執行的Script程式位置在那里。您也可以用"#! /bin/bash"、"#!/bin/tcsh"等等,來指定使用特定的Shell?!?br />   echo是個bash的內建指令。 

      *************************

      接下來,執行hello這個script: 
      要執行一個Script的方式有很多種?!?br />
      *************************

      第一種 : 將hello這個檔案的權限設定為可執行?!?br />   [foxman@foxman bash]# chmod 755 hello 
      執行 
      [foxman@foxman bash]# ./hello 
      hello world 

      *************************

      第二種 : 使用bash內建指令"source"或"."?!?br />   [foxman@foxman bash]# source hello 
      hello world 
      或 
      [foxman@foxman bash]# . hello 
      hello world 

      *************************

      第三種 : 直接使用sh/bash/tcsh指令來執行?!?br />   [foxman@foxman bash]# sh hello 
      hello world 
      或 
      [foxman@foxman bash]# bash hello 
      hello world 

      *************************

      Bash執行選項 

      *************************

      -c string : 讀取string來當命令。 
      -i : 互動介面?!?br />   -s : 由stdin讀取命令。 
      - : 取消往后選項的讀取?!?br />   -norc : 不要讀~/.bashrc來執行?!?br />   -noprofile : 不要讀/etc/profile、~/.bash_profile、~/.bash_login、~/.profile等等來執行?!?br />   -rcfile filename : 執行filename,而非~/.bashrc 
      -version : 顯示版本?!?br />   -quiet : 啟動時不要哩唆?!?br />   -login : 確保bash是個login shell?!?br />   -nobraceexpansion : 不要用curly brace expansion({}符號展開)?!?br />   -nolineediting : 不用readline來讀取命令列?!?br />   -posix : 改采Posix 1003.2標準?!?br />

      用于自動備份的Shell Script


      一個用于自動備份的Shell Script
      我們先前提到,可利用Shell Script搭配crond來作定期的工作。要作定期性的工作,在UNIX上,就是與crond的搭配運用?!?br />
      *************************

      首先我們先來研究如何對系統進行備份?!?br />   要對系統進行備份,不外乎便是利用一些壓縮工具。在許多UNIX系統上,tar及gzip是de facto的資料交換標準。我們經常可以看見一些tar.gz或tgz檔,這些檔案,被稱為tarball。當然了,您也可以用bzip2、zip等等壓 縮工具來進行壓縮,不必限定于gzip。但tar配合gzip是最普遍的,也是最方便的方式。 

      要將我們想要的資料壓縮起來,進行備份,可以結合tar及gzip一起進行。方式有很多種,最常用的指令是以下這一種: 

      tar -c file/dir ... | gzip -9 > xxxx.tar.gz 

      您也可以分開來做: 

      tar -r file/dir ... -f xxxx.tar 
      gzip -9 xxxx.tar 

      或 

      tar -r file/dir ... -f xxxx.tar 
      gzip -9 < xxxx.tar > xxxx.tar.gz 

      *************************

      在解過Linux下檔案備份的基本知識后,我們來寫一個將檔案備份的Script?!?br />   #!/bin/sh 
      # Filename : backup 

      DIRS="/etc /var /your_directories_or_files" 
      BACKUP="/tmp/backup.tgz" 

      tar -c $DIRS | gzip -9 > $BACKUP 

      其中DIRS放的是您要備份的檔案及目錄,BACKUP是您的備份檔??刹灰獙?tmp放進DIRS中,那樣做,您是在做備份的備份,可能將您的硬碟塞爆。 


      *************************

      接下來測試 
      [foxman@foxman bash]# chmod 755 backup 
      [foxman@foxman bash]# ./backup 

      執行完成后在/tmp就會有一個backup.tgz,里面儲存了您重要的資料。您可用 

      gzip -dc /tmp/backup.tgz | tar -vt 
      或 
      tar vtfz /tmp/backup.tgz 

      來看看里面的檔案列表?!?br />
      要解開時,可用以下指令來完成復原: 

      gzip -dc /tmp/backup.tgz | tar -xv 
      或 
      tar xvfz /tmp/backup.tgz 

      備份通常是僅備份系統通常最重要的部份,/etc可說是不可缺少的一部份。另外,看您系統中有那些重要的資料需要備份。通常來說,您沒有必要備份 /bin、/sbin、/usr/bin、/usr/sbin、/usr/X11R6/bin等等這些執行檔目錄。只要備份您重要的檔案即可,別把整個硬 碟備份,那是蠻呆的動作?!?br />
      *************************

      如果您有許多臺機器,可利用其中一臺任務較輕的內部網路主機,做為主要備份主機。將所有機器都自動執行備份,然后利用NFS/Coda/Samba等網路檔案系統,將備份的資料放到該備份機器中,該機器則定時收取備份資料,然后您再由該機器中進行一次備份。 
      這里是整個系統備份方案的圖示?!?br />
      在您進行之前,先解一下,系統中那些是要備份的,那些是不需要的?!?br />
      *************************

      新的backup
      #!/bin/sh 
      HOSTNAME=`hostname` 
      DIRS="/etc /var /your_important_directory" 
      BACKUP="/tmp/$HOSTNAME.tgz" 
      NFS="/mnt/nfs" 

      tar -c $DIRS | gzip -9 > $BACKUP 
      mv -f $BACKUP $NFS 


      *************************

      備份主機內的Script : collect_backup
      #!/bin/sh 
      NFS="/mnt/nfs" 
      BACKUP="/backup" 

      mv -f $NFS/*.tgz $BACKUP 


      在此,您不能夠將所有備份都直接放在/mnt/nfs,這是危險的。萬一任一臺機器不小心將/mnt/nfs所有內容刪除,那么備份就會消失。因此,您需要將/mnt/nfs移到一個只有該備份主機可存取的目錄中?!?br />

      *************************

      當這些個別的Script都測試好以后,接下來我們將他們放到crontab里面。找到您的crontab,它的位置可能在/var/spool/cron/crontabs/root、/etc/crontab、/var/cron/tabs/root?!?br />   在crontab中選擇以下之一加入(看您定期的時間): 

      Slackware : /var/spool/cron/crontabs/root
      01 * * * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每小時(太過火一點) 
      30 16 * * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每日16:30,下班前備份 
      30 16 * * 0 /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每周一16:30 
      0 5 1 * * /full_backup_script_path/backup 1> /dev/null 2> /dev/null # 每月一號5:0 
      RedHat/Debian : /etc/crontab
      RedHat可直接將backup放入/etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly。或采用如上加入/etc/crontab的方式: 
      有關crontab的用法,可查"man 5 crontab",在此不詳述?!?br />
      備份主機的設定類同。 

      注意: 所有機器不要同時進行備份,否則網路會大塞車。備份主機收取備份的時間要設為最后,否則會收不到備份資料。您可以在實作后,將時間間隔調整一下?!?br />

      *************************

      看看,兩個小小不到三行的Shell Script,配合cron這個定時工具??梢宰屧拘枰臅r多個小時的人工備份工作,簡化到不到十分鐘。善用您的想像力,多加一點變化,可你讓您的生活變得輕松異常,快樂悠哉。


      檔案系統檢查

      系統安全一向是大多數電腦用戶關心的事,在UNIX系統中,最重視的事,即系統中有沒有"木馬"(Trojan horse)。不管Trojan horse如何放進來的,有一點始終會不變,即被放置木馬的檔案,其檔案日期一定會被改變,甚至會有其它的狀態改變。此外,許多狀況下,系統會多出一些不 知名的檔案。因此,平日檢查整個檔案系統的狀態是否有被改變,將所有狀態有改變的檔案,以及目前有那些程式正在執行,自動報告給系統管理員,是個避免坐上 "木馬"的良方?!?br />
      *************************

      #!/bin/sh 
      # Filename : whatever_you_name_it 
      DIRS="/etc /home /bin /sbin /usr/bin /usr/sbin /usr/local /var /your_directory" 
      ADMIN="email@your.domain.com" 
      FROM="admin@your.domain.com" 
      # 寫入Sendmail的標頭 
      echo "Subject: $HOSTNAME filesystem check" > /tmp/today.mail 
      echo "From: $FROM" >> /tmp/today.mail 
      echo "To: $ADMIN" >> /tmp/today.mail 
      echo "This is filesystem report comes from $HOSTNAME" >> /tmp/today.mail 
      # 報告目前正在執行的程式 
      ps axf >> /tmp/today.mail 
      # 檔案系統檢查 
      echo "File System Check" >> /tmp/today.mail 
      ls -alR $DIRS | gzip -9 > /tmp/today.gz 
      zdiff /tmp/today.gz /tmp/yesterday.gz >> /tmp/today.mail 
      mv -f /tmp/today.gz /tmp/yesterday.gz 
      # 寄出信件 
      sendmail -t < /tmp/today.mail 

      然后把它放到一個不顯眼的地方去,讓別人找不到?!?br />
      把它加入crontab中?!?br />
      30 7 * * * /full_check_script_path/whatever_you_name_it 1> /dev/null 2> /dev/null #上班前檢查 

      有些檔案是固定會更動的,像/var/log/messages、/var/log/syslog、/dev/ttyX等等,不要太大驚小怪。


      控制圈for

      演示了幾個簡單的Shell Script,相信您應該對Shell Script有點概念了?,F在我們開始來仔細研究一些較高等的Shell Script寫作。一些進一步的說明,例如"$"、">"、"<"、">>"、"1>"、"2>"符號的使用,會在 稍后解釋?!?br />
      *************************

      for name [ in word; ] do list ; done
      控制圈?!?br />   word是一序列的字,for會將word中的個別字展開,然后設定到name上面。list是一序列的工作。如果[in word;]省略掉,那么name將會被設定為Script后面所加的參數?!?br />

      *************************

      例一: 
      #!/bin/sh 

      for i in a b c d e f ; do 
      echo $i 
      done 

      它將會顯示出a到f?!?br />

      *************************

      例二: 另一種用法,A-Z
      #!/bin/sh 
      WORD="a b c d e f g h i j l m n o p q r s t u v w x y z" 

      for i in $WORD ; do 
      echo $i 
      done 

      這個Script將會顯示a到z。 


      *************************

      例三 : 修改副檔名
      如果您有許多的.txt檔想要改名成.doc檔,您不需要一個一個來?!?br />   #!/bin/sh 

      FILES=`ls /txt/*.txt` 

      for txt in $FILES ; do 
      doc=`echo $txt | sed "s/.txt/.doc/"` 
      mv $txt $doc 
      done 

      這樣可以將*.txt檔修改成*.doc檔。 


      *************************

      例四 : meow
      #!/bin/sh 
      # Filename : meow 
      for i ; do 
      cat $i 
      done 

      當您輸入"meow file1 file2 ..."時,其作用就跟"cat file1 file2 ..."一樣。 


      *************************

      例五 : listbin 
      #!/bin/sh 
      # Filename : listbin 

      for i in /bin/* ; do 
      echo $i 
      done 

      當您輸入"listbin"時,其作用就跟"ls /bin/*"一樣?!?br />

      *************************

      例六 : /etc/rc.d/rc 
      拿一個實際的例來說,Red Hat的/etc/rc.d/rc的啟動程式中的一個片斷。 

      for i in /etc/rc.d/rc$runlevel.d/S*; do 
      # Check if the script is there. 
      [ ! -f $i ] && continue 

      # Check if the subsystem is already up. 
      subsys=${i#/etc/rc.d/rc$runlevel.d/S??} 
      [ -f /var/lock/subsys/$subsys ] || \ 
      [ -f /var/lock/subsys/${subsys}.init ] && continue 

      # Bring the subsystem up. 
      $i start 
      done 

      這個例中,它找出/etc/rc.d/rcX.d/S*所有檔案,檢查它是否存在,然后一一執行?!?br />

      流程控制case

      case word in [ pattern [ | pattern ] ... ) list ;; ] ... esac
      case/esac的標準用法大致如下: 
    case $arg in 
      pattern | sample) # arg in pattern or sample 
      ;; 
      pattern1) # arg in pattern1 
      ;; 
      *) #default 
      ;; 
    esac 
      arg是您所引入的參數,如果arg內容符合pattern項目的話,那么便會執行pattern以下的程式碼,而該段程式碼則以兩個分號";;"做結尾?!?br />
      可以注意到"case"及"esac"是對稱的,如果記不起來的話,把"case"顛倒過來即可?!?br />

    *************************

      例一 : paranoia
    #!/bin/sh 
    case $1 in 
        start | begin) 
         echo "start something" 
        ;; 
        stop | end) 
         echo "stop something" 
        ;; 
        *) 
         echo "Ignorant" 
        ;; 
    esac 

      執行
      [foxman@foxman bash]# chmod 755 paranoia 
      [foxman@foxman bash]# ./paranoia 
      Ignorant 
      [foxman@foxman bash]# ./paranoia start 
      start something 
      [foxman@foxman bash]# ./paranoia begin 
      start something 
      [foxman@foxman bash]# ./paranoia stop 
      stop something 
      [foxman@foxman bash]# ./paranoia end 
      stop something 

    *************************

      例二 : inetpanel
      許多的daemon都會附上一個管理用的Shell Script,像BIND就附上ndc,Apache就附上apachectl。這些管理程式都是用shell script來寫的,以下示一個管理inetd的shell script。 
    #!/bin/sh 

    case $1 in 
      start | begin | commence) 
        /usr/sbin/inetd 
      ;; 
      stop | end | destroy) 
        killall inetd 
      ;; 
      restart | again) 
        killall -HUP inetd 
      ;; 
      *) 
        echo "usage: inetpanel [start | begin | commence | stop | end | destory | restart | again]" 
      ;; 
    esac 


    *************************

      例三 : 判斷系統
      有時候,您所寫的Script可能會跨越好幾種平臺,如Linux、FreeBSD、Solaris等等,而各平臺之間,多多少少都有不同之處,有時候需要判斷目前正在那一種平臺上執行。此時,我們可以利用uname來找出系統資訊。 
    #!/bin/sh 

    SYSTEM=`uname -s` 

    case $SYSTEM in 
      Linux) 
        echo "My system is Linux" 
        echo "Do Linux stuff here..." 
      ;; 
      FreeBSD) 
        echo "My system is FreeBSD" 
        echo "Do FreeBSD stuff here..." 
      ;; 
      *) 
        echo "Unknown system : $SYSTEM" 
        echo "I don't what to do..." 
      ;; 
    esac 


      流程控制select

      select name [ in word; ] do list ; done
      select顧名思義就是在word中選擇一項。與for相同,如果[in word;]省略,將會使用Script后面所加的參數。 
      例:
    #!/bin/sh 
    WORD="a b c" 

    select i in $WORD ; do 
     case $i in 
      a) 
       echo "I am A" 
      ;; 
      b) 
       echo "I am B" 
      ;; 
      c) 
       echo "I am C" 
      ;; 
      *) 
       break; 
      ;; 
     esac 
    done 

      執行結果
      [foxman@foxman bash]# ./select_demo 
    1) a 
    2) b 
    3) c 
    #? 1 
    I am A 
    1) a 
    2) b 
    3) c 
    #? 2 
    I am B 
    1) a 
    2) b 
    3) c 
    #? 3 
    I am C 
    1) a 
    2) b 
    3) c 
    #? 4 


      返回狀態Exit

      在繼續下去之前,我們必須要切入另一個話題,即返回狀態值 - Exit Status。因為if/while/until都遷涉到了使用Exit Status來控制程式流程的問題?!?br />
      *************************

      許多人都知道,在許多語言中(C/C++/Perl....),都有一個exit的函數,甚至連Bash自己都有個exit的內建命令。而exit后面所帶的數字,便是返回狀態值 - Exit Status?!?br />   返回狀態值可以使得程式與程式之間,利用Shell script來結合的可能性大增,利用小程式,透過Shell script,來完成很雜的工作?!?br />
      在shell中,返回值為零表示成功(True),非零值為失敗(False)?!?br />

      *************************

      舉例來說,以下這個兩個小程式yes/no分別會返回0/1(成功/失敗): 
      /* yes.c */ 
      void main(void) { exit(0); } 
      /* no.c */ 
      void main(void) { exit(1); } 
      那么以下這個"YES"的shell script便會顯示"YES"?!?br />   #!/bin/sh 
      # YES 
      if yes ; then 
      echo "YES" 
      fi 
      而"NO"不會顯示任何東西?!?br />   #!/bin/sh 
      # NO 
      if no ; then 
      echo "YES" 
      fi 

      *************************

      test express 
      [ express ] 
      在Shell script中,test express/[ express ]這個語法被大量地使用,它是個非常實用的指令。由于它的返回值即Exit Status,經常被運用在if/while/until的場合中。而在后面,我們也會大量運用到,在進入介紹if/while/until之前,有必要 先解一下?!?br />
      其返回值為0(True)或1(False),要看表述(express)的結果為何。 

      express格式 

      -b file : 當檔案存在并且屬性是Block special(通常是/dev/xxx)時,返回True?!?br />   -c file : 當檔案存在并且屬性是character special(通常是/dev/xxx)時,返回True?!?br />   -d file : 當檔案存在并且屬性是目錄時,返回True?!?br />   -e file : 當檔案存在時,返回True?!?br />   -f file : 當檔案存在并且是正常檔案時,返回True。 
      -g file : 當檔案存在并且是set-group-id時,返回True?!?br />   -k file : 當檔案存在并且有"sticky" bit被設定時,返回True?!?br />   -L file : 當檔案存在并且是symbolic link時,返回True?!?br />   -p file : 當檔案存在并且是name pipe時,返回True?!?br />   -r file : 當檔案存在并且可讀取時,返回True?!?br />   -s file : 當檔案存在并且檔案大小大于零時,返回True。 
      -S file : 當檔案存在并且是socket時,返回True?!?br />   -t fd : 當fd被開啟為terminal時,返回True?!?br />   -u file : 當檔案存在并且set-user-id bit被設定時,返回True?!?br />   -w file : 當檔案存在并且可寫入時,返回True。 
      -x file : 當檔案存在并且可執行時,返回True?!?br />   -O file : 當檔案存在并且是被執行的user id所擁有時,返回True?!?br />   -G file : 當檔案存在并且是被執行的group id所擁有時,返回True。 
      file1 -nt file2 : 當file1比file2新時(根據修改時間),返回True?!?br />   file1 -ot file2 : 當file1比file2舊時(根據修改時間),返回True?!?br />   file1 -ef file2 : 當file1與file2有相同的device及inode number時,返回True?!?br />   -z string : 當string的長度為零時,返回True。 
      -n string : 當string的長度不為零時,返回True?!?br />   string1 = string2 : string1與string2相等時,返回True。 
      string1 != string2 : string1與string2不相等時,返回True?!?br />   ! express : express為False時,返回True?!?br />   expr1 -a expr2 : expr1及expr2為True?!?br />   expr1 -o expr2 : expr1或expr2其中之一為True?!?br />   arg1 OP arg2 : OP是-eq[equal]、-ne[not-equal]、-lt[less-than]、-le[less-than-or-equal]、-gt [greater-than]、-ge[greater-than-or-equal]的其中之一?!?br />


      *************************

      在Bash中,當錯誤發生在致命信號時,bash會返回128+signal number做為返回值。如果找不到命令,將會返回127。如果命令找到了,但該命令是不可執行的,將返回126。除此以外,Bash本身會返回最后一個 指令的返回值。若是執行中發生錯誤,將會返回一個非零的值?!?br />   Fatal Signal : 128 + signo 
      Can't not find command : 127 
      Can't not execute : 126 
      Shell script successfully executed : return the last command exit status 
      Fatal during execution : return non-zero

      流程控制if

      if list then list [ elif list then list ] ... [ else list ] fi
      幾種可能的寫法 

    *************************

    第一種 
    if list then 
     do something here 
    fi 
    當list表述返回值為True(0)時,將會執行"do something here"?!?br />
    例一 : 當我們要執行一個命令或程式之前,有時候需要檢查該命令是否存在,然后才執行?!?br /> if [ -x /sbin/quotaon ] ; then 
      echo "Turning on Quota for root filesystem" 
      /sbin/quotaon / 
    fi 

    例二 : 當我們將某個檔案做為設定檔時,可先檢查是否存在,然后將該檔案設定值載入?!?br /> # Filename : /etc/ppp/settings 
    PHONE=1-800-COLLECT 

    #!/bin/sh 
    # Filename : phonebill 
    if [ -f /etc/ppp/settings ] ; then 
      source /etc/ppp/settings 
      echo $PHONE 
    fi 
    執行 
    [foxman@foxman ppp]# ./phonebill 
    1-800-COLLECT 


    *************************

    第二種 
    if list then 
     do something here 
    else 
     do something else here 
    fi 
    例三 : Hostname 
    #!/bin/sh 
    if [ -f /etc/HOSTNAME ] ; then 
      HOSTNAME=`cat /etc/HOSTNAME` 
    else 
      HOSTNAME=localhost 
    fi 


    *************************

    第三種 
    if list then 
     do something here 
    elif list then 
     do another thing here 
    fi 
    例四 : 如果某個設定檔允許有好幾個位置的話,例如crontab,可利用if then elif fi來找尋?!?br /> #!/bin/sh 

    if [ -f /etc/crontab ] ; then 
      CRONTAB="/etc/crontab" 
    elif [ -f /var/spool/cron/crontabs/root ] ; then 
      CRONTAB="/var/spool/cron/crontabs/root" 
    elif [ -f /var/cron/tabs/root ] ; then 
      CRONTAB="/var/cron/tabs/root" 
    fi 
    export CRONTAB 


    *************************

    第四種 
    if list then 
     do something here 
    elif list then 
     do another thing here 
    else 
     do something else here 
    fi 
    例五 : 我們可利用uname來判斷目前系統,并分別做各系統狀況不同的事?!?br /> #!/bin/sh 

    SYSTEM=`uname -s` 

    if [ $SYSTEM = "Linux" ] ; then 
     echo "Linux" 
    elif [ $SYSTEM = "FreeBSD" ] ; then 
     echo "FreeBSD" 
    elif [ $SYSTEM = "Solaris" ] ; then 
     echo "Solaris" 
    else 
     echo "What?" 
    fi 

    控制圈while/until

    while list do list done
    當list為True時,該圈會不停地執行?!?br /> 例一 : 無限回圈寫法 
    #!/bin/sh 

    while : ; do 
     echo "do something forever here" 
     sleep 5 
    done 

    例二 : 強迫把pppd殺掉?!?br /> #!/bin/sh 

    while [ -f /var/run/ppp0.pid ] ; do 
      killall pppd 
    done 


    *************************

    until list do list done
    當list為False(non-zero)時,該圈會不停地執行。 
    例一 : 等待pppd上線?!?br /> #!/bin/sh 
    until [ -f /var/run/ppp0.pid ] ; do 
      sleep 1 
    done 


      參數與變數

      在繼續下去介紹function之前,我們必須停下來介紹"參數與變數"?!?br />
      *************************

      參數(Parameters)是用來儲存"值"的資料型態,有點像是一般語言中的變數。它可以是個名稱(name)、數字(number)、或者是以下所列出來一些特殊符號(Special Parameters)?!?br />   在shell中,變數是由name形式的參數所構成的。 


      *************************

      在前面的許多例中,我們事實上已經看到許多參數的運用。要設定一個Parameter實際很簡單: 
      name=value 

      例如說: 

      MYHOST="foxman" 

      而要使用它時,則是加個"$"符號?!?br />
      echo $MYHOST 

      *************************

      位置參數(Positional Parameters) 

      *************************

      所謂的位置參數便是0,1,2,3,4,5,6,7,8,9...。使用時,用$0,$1,$2...?!?br />   位置參數是當script被載入時,后面所附加的參數。$0是本身,$1則為第一個參數,$2為第二個,依此類推。而當Positional Parameters被function所使用時,它們會被暫時取代(下一節會介紹function)?!?br />
      例如以下這個script: 
      #!/bin/sh 
      # Filename : position 
      echo $0 
      echo $1 

      執行時: 
      [foxman@foxman bash]# ./position abc 
      ./position 
      abc 

      當位置參數超過兩位數時,有特別的方法來展開,稱為Expansion?!?br />
      *************************

      特殊參數(Speical Parameters) 
      這些符號,非常不人性,對新手來說很困擾。但上手后,會覺得方便無比,有些如果您看不懂的話,就--算了,不用浪費太多時間在上面?!?br />
      *************************

      * 星號 
      將Positional Parameters合成一個參數,其間隔為IFS內定參數的第一個字元(見內建變數一節)?!?br />   例: 
      #!/bin/sh 
      # starsig 
      echo $* 

      執行: 
      [foxman@foxman bash]# starsig a b c d e f g 
      a b c d e f g 

      *************************

      @ at符號 
      與*星號類同。不同之處在于不參照IFS。 

      例: 
      #!/bin/sh 
      # atsig 
      echo $@ 

      執行: 
      [foxman@foxman bash]# atsig a b c d e f g 
      a b c d e f g 


      *************************

      # 井字號 
      展開Positional parameters的數量?!?br />
      例: 
      #!/bin/sh 
      # poundsig 
      echo $# 

      執行 
      [foxman@foxman bash]# poundsig a b c d e f g 
      7 

      *************************

      ? 問號 
      最近執行的foreground pipeline的狀態。 


      *************************

      - 減號 
      最近執行的foreground pipeline的選項參數?!?br />
      *************************

      $ 錢錢錢 
      本身的Process ID。 

      [foxman@foxman bash]# ps ax | grep bash 
      1635 p1 S  0:00 /bin/bash 

      [foxman@foxman bash]# echo $$ 
      1635 

      *************************

      ! 驚號 
      最近執行背景命令的Process ID?!?br />
      *************************

      0 零 
      在Positional Parameters一部份已經說明過了,是執行的shell script本身。但如果是用"bash -c",則$0被設為第一個參數?!?br />
      [foxman@foxman bash]# echo $0 
      /bin/bash 

      *************************

      _ 底線符號 
      顯示出最后一個執行的命令。 

      [foxman@foxman bash]# echo $_ 
      bash 


      *************************

      內建變數(Shell Variables) 
      Bash有許多內建變數,像PATH、HOME、ENV......等等。這些內建變數將在另一節中,專門一一說明。

      函數function

      [ function ] name () { list; }
      function的參數是Positional Paraments?!?br />
      例 
    #!/bin/sh 

    function func() { 
     echo $1 
     echo $2 
     return 1 
    } 

    func "Hello" "function" 

      局部變數可用local來宣告?!?br />
      函數可export,使用下一層的shell可以使用?!?br />
      函數可遞,沒有遞層數的限制。

      Bash內建指令集 

      以下的命令,大部份都沒有使用例,您可能會看不出所以然,摸不著頭腦。在我加入例說明前,建議您"man bash",然后自己實際操作一次?!?br />
      *************************
      : [arguments] 
      不做任何事,除了[arguments]一些參數展開及一些特定重導向的作業外?!?br />
      永遠返回零。它的用法跟true一樣?!?br />
      *************************
      . filename [arguments] 
      source filename [arguments] 
      由filename中讀取命令,并執行?!?br />   您會在/etc/rc.d/*中發現很多 
      . /xxxx 
      的指令,而xxxx的permission都不是可執行的。事實上,在tcsh中,需要用 
      source /xxxx 
      來做同樣的指令?!?br />   注意到"."的后面是有空格的(比較一下". /"跟"./",不一樣)。filename是內含指令的純文字檔即可,無須chmod 755 filename?!?br />
      例
      filename : my_source 
      DEV=lo 
      IP=127.0.0.1 
      NETMASK=255.0.0.0 
      BROADCAST=127.255.255.255 

      ifconfig $IP netmask $NETMASK broadcast $BROADCAST dev $DEV 

      接下來 
      . my_source 
      或 
      source my_source 

      便可執行該script,而不需要"chmod 755 my_source" 

      *************************
      alias [name[=value] ...] 
      昵稱命令 
      例如您如果來自DOS的世界,對UNIX的指令不習慣,可用alias來修改,以符合您的習慣?!?br />
      例
      alias ls="ls --color" 
      alias dir="ls" 
      alias cd..="cd .." 
      alias copy="cp -f" # dangerous, recommend, "cp -i" 
      alias del="rm -f" # dangerous, recommend, "rm -i" 
      alias move="mv -f" # dangerous, recommend, "mv -i" 
      alias md="mkdir" 
      alias rd="rmdir" 

      *************************
      unalias [-a] [name ...] 
      unalias取消alias的設定。"unalias -a"將全部alias取消。 

      例
      unalias copy 

      *************************
      bg [jobspec] 
      將指定任務放到背景中,如果jobspec未指定,內定為目前的?!?br />
      *************************
      fg [jobspec] 
      將指定任務放到前景中,如果jobsepc沒有指定,那么內定為目前的?!?br />
      *************************
      jobs [-lnp] [ jobspec ... ] 
      第一種形式列出目前正在工作的任務?!?br />   -l : 除了列出一般資訊外,還列出Process IDs。 
      -p : 僅列出該工作群"首腦"(Process group leader)的Process ID. 
      -n : 則僅列出有改變的jobs的狀態。 
      如果給定jobspec,輸出資訊則只有該jobspec?!?br />
      返回值為零,除非有非法的選項發生?!?br />
      jobs -x command [ args ... ] 

      如果使用第二種形式(-x),jobs取代指定的command及args,并執行返回其Exit Status?!?br />
      *************************
      kill [-s sigspec | -sigspec] [pid | jobspec] ... 
      將sigspec的信號送到pid或jobspec。 
      sigspec可以是SIGKILL/KILL這種形式或是信號號碼。如果sigspec是signal name,則大小寫無關,而且可以沒有SIG?!?br />   kill -l [signum] 
      列出信號名稱?!?br />
      [foxman@foxman bash]# kill -l 
      1) SIGHUP    2) SIGINT    3) SIGQUIT   4) SIGILL 
      5) SIGTRAP   6) SIGIOT    7) SIGBUS    8) SIGFPE 
      9) SIGKILL   10) SIGUSR1   11) SIGSEGV   12) SIGUSR2 
      13) SIGPIPE   14) SIGALRM   15) SIGTERM   17) SIGCHLD 
      18) SIGCONT   19) SIGSTOP   20) SIGTSTP   21) SIGTTIN 
      22) SIGTTOU   23) SIGURG   24) SIGXCPU   25) SIGXFSZ 
      26) SIGVTALRM  27) SIGPROF   28) SIGWINCH  29) SIGIO 
      30) SIGPWR 

      *************************
      wait [n] 
      等待指定的行程,并返回其結束狀態。n可以是個jobspec或Process ID。如果n未指定,則等待所有的子行程,及返回值為零。若n為不存在的job或process,則返回127。否則,返回值為最后一個 job/process的Exit Status。 

      *************************
      bind [-m keymap] [-lvd] [-q name] 
      bind [-m keymap] -f filename 
      bind [-m keymap] keyseq:function-name 
      顯示出目前readline的按鍵及鏈結函數設定或是巨集?!?br />
      -m keymap : 設定keymap binding?!?br />   -l : 顯示出所有readline function的名稱?!?br />   -v : 顯示出目前的function name及bindings?!?br />   -d : 顯示出function name及bindings?!?br />   -f filename : 從filename讀取key bindings?!?br />   -q function : 詢問那個按鍵觸發function。 

      *************************
      break [n] 
      跳出控制回圈for/while/until中使用。如果有指定n,則跳出n層。n必須是大于等于1。若n大于巢狀圈數,則所有的圈都會跳離。返回值回零。 

      *************************
      continue [n] 
      還原控制回圈for/while/until中使用。如果有指定n,則返回n層。n必須是大于等于1。若n大于巢狀圈數,則還原到最上層。返回值回零。 

      *************************
      exit [n] 
      離開程式。n是Exit Status?!?br />
      *************************
      return [n] 
      在function中使用。n為返回值,其作用與Exit Status一樣。 

      *************************
      builtin shell-builtin [arguments] 
      執行內建函數。當您定義了與內建函數相同的指令時,可用此命令來執行內建函數?!?br />
      *************************
      cd [dir] 
      更換目錄到dir。如果沒有指定,內定為HOME所指定的目錄?!?br />
      *************************
      command [-pVv] command [arg ...] 
      用command指定可取消正常的shell function尋找。只有內建命令及在PATH中找得到的才會被執行。"-p"選項,搜尋命令的方式是用PATH來找。"-V"或"-v"選項,會顯示出該命令的一些簡約描述?!?br />
      *************************
      declare [-frxi] [name[=value]] 
      typeset [-frxi] [name[=value]] 
      宣告參數并給它們設定屬性。如果沒有給定名稱,將會顯示各參數值?!?br />
      -f : 僅使用函數名稱?!?br />   -r : 將name設為readonly?!?br />   -x : 將name輸出給后續環境使用?!?br />   -i : 該參數被設為integer來使用,可用于算術表述。 

      用"+"時,關閉該屬性?!?br />
      *************************
      dirs [-l] [+/-n] 
      顯示目前記憶的目錄。目錄可透過pushd/popd來操作。 

      +n : 顯示開始的記錄n個。 
      -n : 顯示結尾的記錄n個?!?br />   -l : 顯示較多的資訊。 

      *************************
      echo [-neE] [arg ...] 
      輸出顯示args,由空白分隔。返回值永為零。 

      -n : 不跳行?!?br />   -e : 啟動"\"符號的解譯。 
      -E : 將ESC解譯功能取消?!?br />
      "\a" : alert(bell),發出聲響?!?br />   "\b" : backspace,倒退。 
      "\c" : suppress trailing newline,不跳行?!?br />   "\f" : form feed,跳行跳格?!?br />   "\n" : new line,新行。 
      "\r" : carriage return,回到行起點?!?br />   "\t" : horizontal tab,水平跳位?!?br />   "\v" : vertical tab,垂直跳位?!?br />   "\\" : 輸出"\"?!?br />   "\nnn" : 輸出ASCII Code號碼nnn(八進位)。 

      *************************
      enable [-n] [-all] [name ...] 
      啟動或關閉內建函數命令。使用"-n"將所有指定命令皆關閉,否則都是啟動的。如果只有"-n"參數,它將會顯示所有關閉的函數。如果只有"-all",它將會顯示所有內建命令?!?br />
      *************************
      eval [arg ...] 
      讀取args,并將args合為一個命令,然后執行。其返回值成為eval的返回值。如果沒有參數,eval返回True?!?br />
      *************************
      exec [[-] command [arguments]] 
      當命令執行時,該命令取代shell,沒有新的process產生。如果第一個參數是"-",shell會將"-"放入第零個參數,傳給command?!?br />
      *************************
      export [-nf] [name[=word]] ... 
      export -p 
      將name輸出給環境,給往后的命令使用。"-f"選項表示name是函數。"-p"顯示出所有export的名稱。"-n"移除name?!?br />
      *************************
      set [--abefhkmnptuvxldCHP] [-o option] [arg ...] 
      -a : 自動將變數標記為可讓后面環境所使用?!?br />   -b : 立即報告被終結的背景程式狀態?!?br />   -e : 當命令(simple-command,見后面)返回非零值時,立即跳出?!?br />   -f : 取消pathname expansion?!?br />   -h : 找出所記憶的函數命令位置。 
      -k : 所有keyword參數都放到環境中?!?br />   -m : 監督模式。 
      -n : 讀取命令,但不要執行??捎糜谡Z法檢查。 
      -p : 打開privileged模式?!?br />   -t : 當讀取一個命令并執行后,立即離開?!?br />   -u : 當參數展開時,把unset參數當成是錯誤。 
      -v : 列出shell input lines?!?br />   -x : 在展開每個simple-command后,bash顯示展開值在PS4上?!?br />   -l : 儲存并還原name binding在for語法中。 
      -d : 關閉hasing command搜尋?!?br />   -C : 跟`noclobber=`一樣。請見內定參數一節?!?br />   -H : 啟動! style history substitution。 
      -P : 在使用像cd這種指令時,不要跟隨symbolic links?!?br />   -- : "--"之后,沒有參數跟在后面?!?br />   - : 指定將所有后面的參數當成是位置參數。 
      -o option-name : option-name可以是以下之一 
      allexport : 與"-a"相同。 
      braceexpand : 啟動Brace Expansion。這是內定設定?!?br />   emacs : 使用emacs-style命令列編輯界面。 
      errexit : 與"-e"相同?!?br />   histexpand : 與"-H"相同。 
      ignoreeof : 效果跟`IGNOREEOF=10`一樣?!?br />   interactive-commands : 允許#做為解?!?br />   monitor : 與"-m"相同?!?br />   noclobber : 與"-C"相同。 
      noexec : 與"-n"相同?!?br />   noglob : 與"-f"相同。 
      nohash : 與"-d"相同?!?br />   notify : 與"-b"相同?!?br />   nounset : 與"-u"相同。 
      physical : 與"-P"相同?!?br />   posix : Bash行為修改為Posix 1003.2標準?!?br />   privileged : 與"-p"相同?!?br />   verbose : 與"-v"相同?!?br />   vi : 使用vi-style命令列編輯程式?!?br />   xtrace : 與"-x"相同?!?br />
      *************************
      unset [-fv] [name ...] 
      移除對映于name的參數。要注意PATH、IFS、PPID、PS1、PS2、UID、EUID不能unset。若RANDOM、SECONDS、 LINENO、HISTCMD被unset,它們會喪失原有意義,既始它們后來被重設也一樣。返回值為True,除非name是不能被unset的?!?br />
      *************************
      fc [-e ename] [-nlr] [first] [last] 
      fc -s [pat=rep] [cmd] 
      修正命令。 

      *************************
      getopts optstring name [args] 
      解析位置參數?!?br />
      *************************
      help [pattern] 
      顯示協助資訊。 

      *************************
      history [n] 
      history -rwan [filename] 
      沒有參數時,會顯示所下命令的歷史記錄。帶有參數"n"則顯示最后n個。 

      其它參數如下: 
      -a : 新增"新歷史"到歷史檔中?!?br />   -n : 讀取尚未讀到歷史中的記錄。 
      -r : 讀取filename做為歷史檔,并用它為目前歷史記錄?!?br />   -w : 將現有歷史記錄寫到filename中?!?br />
      *************************
      let arg [arg ...] 
      算術表述。請參考算術表述一節。 

      *************************
      local [name[=value] ...] 
      產生一個局部參數。如果用于function,則其作用圍在function內及其子函數。 

      *************************
      logout 
      離開login shell?!?br />
      *************************
      popd [+/-n] 
      移除目錄堆疊。"+n"移除上面n個,"-n"移除下面n個?!?br />

      *************************
      pushd [dir] 
      pushd +/-n 
      將目錄新增到目錄堆疊的最上面。"+n"旋轉該堆疊,使第n個目錄變成最上面。"-n"旋轉該堆疊,使倒數第n個目錄變成最上面?!?br />
      *************************
      pwd 
      列出目前工作目錄的絕對路徑?!?br />
      *************************
      read [-r] [name ...] 
      讀進一行,然后第一個字設到第一個name,第二個設到第二個name,依此類推。如果沒有name在參數中,則read會將值設到REPLY。返回值為零,除非遇到End-Of-File。若有"-r"選項,則"\n"被考慮為該行的一部份。 

      *************************
      readonly [-f] [name ...] 
      readonly -p 
      將給定的name標記為readonly。如果是"-f"選項,則函數也一樣被標記為readonly。"-p"會列出所有readonly的name。"--"取消檢查剩余的參數。 

      *************************
      shift [n] 
      Positional Parameters從n+1...開始,會被改為$1...。n若為零,則沒有改變。n若未給定,則內定為1。n必須是非負數,并且小于或等于$#。若n大于$#,則沒有改變。返回值為零,除非n大于$#或小于零?!?br />
      *************************
      suspend [-f] 
      暫停這個shell的執行,直到它收到SIGCONT信號。"-f"選項則是叫login shell不要抱怨,不過還是一樣暫停。返回狀態零,除非該shell是個login shell,而且沒有"-f"選項?!?br />
      *************************
      test expr 
      [ expr ] 
      我們在Exit Status的部份已經說過了,不再重?!?br />
      *************************
      times 
      列出該shell的累積的使用者及系統時間及從shell執行的process時間,返回值為零。 

      ------------------------------------------------------------------------------
      trap [-l] [arg] [sigspec] 
      當收到sigspec信號時,執行arg命令。"-l"顯示出信號名稱及號碼?!?br />
      *************************
      type [-all] [-type | -path] name [name ...] 
      沒有參數的狀況下,它會顯示出shell如何解譯name做為命令。如果有"-type",它將會顯示alias、keyword、 function、builtin或file。如果有"-path"的參數,它將會顯示該命令的路徑,找不到的話,不顯示任何東西。如果有"-all"的 參數,它將會顯示所有可執行name的可能路徑。type接受"-a"、"-t"、"-p"做為縮寫?!?br />
      *************************
      ulimit [-SHacdfmstpnuv [limit]] 
      ulimit提供了對shell的可獲取資源控制的功能?!?br />
      -a : 報告目前所有限制?!?br />   -c : 設定最大可產生的core檔案。 
      -d : 行程資料段(process's data segment)最大值?!?br />   -f : 可被這個shell產生的最大檔案?!?br />   -m : resident set size最大值?!?br />   -s : 堆疊最大值。 
      -t : CPU TIME最大值(以秒計算)?!?br />   -p : pipe size in 512-byte blocks的最大值。 
      -n : 可開啟的file descriptors最大值?!?br />   -u : 單一使用者可使用的最大process數?!?br />   -v : 該shell最大虛擬記憶體可用值?!?br />
      所有項目是以1024做為單位?!?br />
      *************************
      umask [-S] [mode] 
      將使用者的file-creation mask設為mode。"-S"選項將mask印成符號形式。


      Bash內建參數

      PPID : 該bash的呼叫者process ID. 

      PWD : 目前的工作目錄?!?br />
      OLDPWD : 上一個工作目錄。 

      REPLY : 當read命令沒有參數時,直接設在REPLY上?!?br />
      UID : User ID?!?br />
      EUID : Effective User ID。 

      BASH : Bash的完整路徑?!?br />
      BASH_VERSION : Bash版本。 

      SHLVL : 每次有Bash執行時,數字加一?!?br />
      RANDOM : 每次這個參數被用到時,就會產生一個亂數在RANDOM上?!?br />
      SECONDS : 從這個Shell一開始啟動后的時間?!?br />
      LINENO : Script的行數?!?br />
      HISTCMD : 歷史記錄數?!?br />
      OPTARG : getopts處理的最后一個選項參數。 

      OPTIND : 下一個要由getopts所處理的參數號碼?!?br />
      HOSTTYPE : 機器種類。 

      OSTYPE : 作業系統名稱?!?br />
      IFS : Internal Field Separator。 

      PATH : 命令搜尋路徑?!?br />   PATH="/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:." 

      HOME : 目前使用者的home directory; 

      CDPATH : cd命令的搜尋路徑?!?br />
      ENV : 如果這個參數被設定,每次有shell script被執行時,將會執行它所設定的檔名做為環境設定?!?br />
      MAIL : 如果這個參數被設定,而且MAILPATH沒有被設定,那么有信件進來時,bash會通知使用者。 

      MAILCHECK : 設定多久時間檢查郵件一次?!?br />
      MAILPATH : 一串的郵件檢查路徑?!?br />
      MAIL_WARNING : 如果有設定的話,郵件被讀取后,將會顯示訊息?!?br />
      PS1 : 提示訊息設定,內定為"bash\$ "。(請詳見提示訊息一節。) 

      PS2 : 第二提示訊息設定,內定為"> "?!?br />
      PS3 : select命令所使用的提示訊息?!?br />
      PS4 : 執行追蹤時用的提示訊息設定,內定為"+ "。 

      HISTSIZE : 命令歷史記錄量,內定為500?!?br />
      HISTFILE : 歷史記錄檔,內定~/.bash_history?!?br />
      HISTFILESIZE : 歷史記錄檔行數最大值,內定500?!?br />
      OPTERR : 如果設為1,bash會顯示getopts的錯誤?!?br />
      PROMPT_COMMAND : 如果設定的話,該值會在每次執行命令前都顯示?!?br />
      IGNOREEOF : 將EOF值當成輸入,內定為10。 

      TMOUT : 如果設為大于零,該值被解譯為輸入等待秒數。若無輸入,當成沒有輸入。 

      FCEDIT : fc命令的內定編輯器?!?br />
      FIGNORE : 請詳見READLINE?!?br />
      INPUTRC : readline的startup file,內定~/.inputrc 

      notify : 如果設定了,bash立即報告被終結的背景程式?!?br />
      history_control, HISTCONTROL : history使用?!?br />
      command_oriented_history : 存入多行指令。 

      glob_dot_filenames : 如果設定了,bash將會把"."包含入檔案路徑中?!?br />
      allow_null_glob_expansion : 如果設定了,bash允許路徑明稱為null string?!?br />
      histchars : history使用?!?br />
      nolinks : 如果設定了,執行指令時,不會跟隨symbolic links?!?br />
      hostname_completion_file, HOSTFILE : 包含與/etc/hosts相同格式的檔名?!?br />
      noclobber : 如果設定了,Bash不會覆寫任何由">"、">&"及"<>"所操作的檔案?!?br />
      auto_resume : 請見任務控制一節?!?br />
      no_exit_on_failed_exec : 如果該值存在,非互動的shell不會因為exec失敗而跳出?!?br />
      cdable_vars : 如果啟動,而cd命令找不到目錄,可切換到參數形態指定的目錄下。


      提示符號

      Bash使用PS1~PS4來顯示提示符號,其格式如下: 

      *************************

      \t : 現在時間?!?br />   \d : 現在日期?!?br />   \n : 新行?!?br />   \s : shell的名稱?!?br />   \w : 目前工作目錄。 
      \W : 目前工作目錄完整路徑。 
      \u : 使用者名稱?!?br />   \h : Hostname。 
      \# : 這個命令的號碼?!?br />   \! : 歷史號碼?!?br />   \$ : 如果EUID是0,則#,否則為$?!?br />   \nnn : 八進位的字元?!?br />   \\ : "\"符號?!?br />   \[ : 開始一序列不可列印的字元?!?br />   \] : 結束一序列不可列印的字元。


      算術表述

      - + 
      ! ~ 
      * / % 
      + - 
      << >> 
      <= >= < > 
      == != 
      & 
      ^ 
      | 
      && 
      || 
      = *= /= %= += -= <<= >>= &= ^= |= 

      重導Redirection

      > 
      >> 
      1> 
      . 
      . 


      語法

      Simple Command 


      Pipelines 


      Lists 

      (list) 
      { list; }
    posted on 2006-06-16 14:20 Alex 閱讀(355) 評論(0)  編輯  收藏 所屬分類: linux
    主站蜘蛛池模板: 亚洲网站免费观看| 91成人免费在线视频| 亚洲欧洲日产国码久在线| 亚洲三区在线观看无套内射| 67194成是人免费无码| 久久精品免费电影| 一级毛片免费播放男男| 亚洲综合成人婷婷五月网址| 久久亚洲国产成人精品性色 | 久久久亚洲精品视频| 免费看国产精品麻豆| 中文字幕无码成人免费视频| 国产成人精品免费久久久久| 一级一级毛片免费播放| MM1313亚洲国产精品| 中文字幕无码精品亚洲资源网久久| 亚洲AV无码专区国产乱码电影| 亚洲人成色77777在线观看大 | 成人亚洲国产va天堂| 中文字幕亚洲第一在线| 最新国产AV无码专区亚洲 | 亚洲国产日韩视频观看| 亚洲最大黄色网址| 91亚洲自偷手机在线观看| 亚洲av无码不卡一区二区三区| 亚洲熟妇中文字幕五十中出| 亚洲精品WWW久久久久久| 亚洲Av无码乱码在线播放| 国产免费av片在线无码免费看| 日本免费人成黄页网观看视频| 97无码免费人妻超级碰碰夜夜 | 亚洲国产女人aaa毛片在线 | 特黄aa级毛片免费视频播放| 国产成人综合亚洲| 边摸边吃奶边做爽免费视频99| 日韩亚洲人成在线综合| 日韩亚洲翔田千里在线| 搜日本一区二区三区免费高清视频 | 亚洲天堂久久精品| 亚洲精品视频观看| 亚洲冬月枫中文字幕在线看|