Thursday 28 June 2007

iPhone

Wednesday 27 June 2007

linux proxy setting up

Proxy and port combination

Most programs (that support proxies at all) support this method. The easiest way to set it up, it to edit /etc/profile.d/proxy.sh file. It should contain the following:

#!/bin/bash
export http_proxy=http://cache.lsbu.ac.uk:8080
export ftp_proxy=http://cache.lsbu.ac.uk:8080

Most programs should then (on next logon) be able to use the proxies. Some may need to be told explicitly though. The proxy hostname is 'proxy.sun.ac.za' and the port is 3128.

Monday 25 June 2007

ubuntu 控制package是否升级

方法1:dpkg



somebody said hold was a status flag to tell apt not to automatically
upgrade a package. apt will place packages on hold if they require
packages that are not currently installable; you can 'apt-get
install pkgname' to explicitly install the package. To put a package on
hold, 'echo pkgname hold | dpkg --set-selections' or use the '=' key on
the package in dselect, or 'echo pkgname install | dpkg
--set-selections' to remove the hold





我们说 hold ,其实是一个状态标志,目的是告诉 apt 停止自动升级某个包裹。


apt 将让一些包裹处于 hold 状态,如果他们请求的包裹现在不可安装;


你能够使用 ‘apt-get install pkgname' 来安装包裹。


为了让包裹置于 hold. 'echo pkgname hold | dpkg --set-selections ' 或在 dselect 中使用 '=' 键于对应的包裹。


移除 hold 用


'echo pkgname install | dpkg --set-selections'



方法2:aptitude



输入aptitude后,进入其界面,

"/" to search the package you want to operate,

"=" HOLD the version not updated in future.







Powered by ScribeFire.

apt-file : packages

apt-file is an application to search for files in the Debian repository. Its use is similar to apt-get, for example:


Update the package contents:


apt-file update


Search some some file:


apt-file search MISSINGFILENAME


Remove the package content files:


apt-file purge



######################

Fedora:

yum whatprovides MISSINGFILENAME

Saturday 23 June 2007

shell 脚本编写 (if [-f ])

为什么要进行shell编程



  在Linux系统中,虽然有各种各样的图形化接口工具,但是
shell仍然是一个非常灵活的工具。Shell不仅仅是命令的收集,而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务自动化,
shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。



  下面,让我们一起来看看shell是如何工作的:



建立一个脚本



 
 Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell)
进行shell编程,因为bash是免费的并且很容易使用。所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下,这些脚本同样可以在
bash的大姐,bourne shell中运行)。



  如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、vi



  等来编写我们的shell程序。



  程序必须以下面的行开始(必须方在文件的第一行):



#!/bin/sh





  符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。



  当编辑好脚本时,如果要执行该脚本,还必须使其可执行。



  要使脚本可执行:



chmod +x filename





  然后,您可以通过输入: ./filename 来执行您的脚本。



注释



  在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。



变量



  在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:



变量名=值



  取出变量值可以加一个美元符号($)在变量前面:





#!/bin/sh

#对变量赋值:

a="hello world"

# 现在打印变量a的内容:

echo "A is:"

echo $a





  在您的编辑器中输入以上内容,然后将其保存为一个文件first。之后执行chmod +x first



  使其可执行,最后输入./first执行该脚本。



  这个脚本将会输出:



A is:

hello world





  有时候变量名很容易与其他文字混淆,比如:





num=2

echo "this is the $numnd"





  这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量:





num=2

echo "this is the ${num}nd"





  这将打印: this is the 2nd



  有许多变量是系统自动设定的,这将在后面使用这些变量时进行讨论。



  如果您需要处理数学表达式,那么您需要使用诸如expr等程序(见下面)。



  除了一般的仅在程序内有效的shell变量以外,还有环境变量。由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。



Shell命令和流程控制



  在shell脚本中可以使用三类命令:



1)Unix 命令:



  虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。



常用命令语法及功能



  echo "some text": 将文字内容打印在屏幕上



  ls: 文件列表



  wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数



  cp sourcefile destfile: 文件拷贝



  mv oldname newname : 重命名文件或移动文件



  rm file: 删除文件



  grep 'pattern' file: 在文件内搜索字符串比如:grep 'searchstring' file.txt



  cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,这是两个完全不同的命令



  cat file.txt: 输出文件内容到标准输出设备(屏幕)上



  file somefile: 得到文件类型



  read var: 提示用户输入,并将输入赋值给变量



  sort file.txt: 对file.txt文件中的行进行排序



  uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq



  expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3



  find: 搜索文件比如:根据文件名搜索find . -name filename -print



  tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile



  basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tux



  dirname file: 返回文件所在路径比如:dirname /bin/tux将返回 /bin



  head file: 打印文本文件开头几行



  tail file : 打印文本文件末尾几行



 
 sed:
Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。
不要和shell中的通配符相混淆。比如:将linuxfocus 替换为 LinuxFocus :cat text.file | sed
's/linuxfocus/LinuxFocus/' > newtext.file



  awk: awk 用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。cat file.txt | awk -F,
'{print $1 "," $3 }'这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如下: Adam Bor,
34, IndiaKerry Miller, 22, USA命令输出结果为:Adam Bor, IndiaKerry Miller, USA



2) 概念: 管道, 重定向和 backtick



  这些不是系统命令,但是他们真的很重要。



  管道 (|) 将一个命令的输出作为另外一个命令的输入。



grep "hello" file.txt | wc -l





  在file.txt中搜索包含有”hello”的行并计算其行数。



  在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。



  重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。



  > 写入文件并覆盖旧文件



  >> 加到文件的尾部,保留旧文件内容。



反短斜线



  使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。



  命令:



find . -mtime -1 -type f -print



  用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:



#!/bin/sh

# The ticks are backticks (`) not normal quotes ('):

tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`





  3) 流程控制



  "if" 表达式 如果条件为真则执行then后面的部分:



if ....; then

  ....

elif ....; then

  ....

else

  ....

fi





  大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存在及是否可读等等…



  通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。



[ -f "somefile" ] :判断是否是一个文件

[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限

[ -n "$var" ] :判断$var变量是否有值

[ "$a" = "$b" ] :判断$a和$b是否相等



  执行man test可以查看所有测试表达式可以比较和判断的类型。



  直接执行以下脚本:



#!/bin/sh

if [ "$SHELL" = "/bin/bash" ]; then

 echo "your login shell is the bash (bourne again shell)"

else

 echo "your login shell is not bash but $SHELL"

fi



  变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。



快捷操作符



  熟悉C语言的朋友可能会很喜欢下面的表达式:



[ -f "/etc/shadow" ] && echo "This computer uses shadow passwors"



 
 这里 &&
就是一个快捷操作符,如果左边的表达式为真则执行右边的语句。您也可以认为是逻辑运算中的与操作。上例中表示如果/etc/shadow文件存在则打印”
This computer uses shadow passwors”。同样或操作(||)在shell编程中也是可用的。这里有个例子:



#!/bin/sh

mailfolder=/var/spool/mail/james

[ -r "$mailfolder" ]' '{ echo "Can not read $mailfolder" ; exit 1; }

echo "$mailfolder has mail from:"

grep "^From " $mailfolder





  该脚本首先判断mailfolder是否可读。如果可读则打印该文件中的"From" 一行。如果不可读则或操作生效,打印错误信息后脚本退出。这里有个问题,那就是我们必须有两个命令:



  -打印错误信息



  -退出程序



  我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。一般函数将在下文提及。



  不用与和或操作符,我们也可以用if表达式作任何事情,但是使用与或操作符会更便利很多。



  case表达式可以用来匹配一个给定的字符串,而不是数字。



case ... in

...) do something here ;;

esac



  让我们看一个例子。 file命令可以辨别出一个给定文件的文件类型,比如:



file lf.gz





  这将返回:



lf.gz: gzip compressed data, deflated, original filename,

last modified: Mon Aug 27 23:09:18 2001, os: Unix



  我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2, gzip 和zip 类型的压缩文件:



#!/bin/sh

ftype=`file "$1"`

case "$ftype" in

"$1: Zip archive"*)

  unzip "$1" ;;

"$1: gzip compressed"*)

  gunzip "$1" ;;

"$1: bzip2 compressed"*)

  bunzip2 "$1" ;;

*) error "File $1 can not be uncompressed with smartzip";;

esac



  您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一个参数值。也就是说,当我们运行:



smartzip articles.zip

$1 就是字符串 articles.zip



  select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户可以从一组不同的值中进行选择。



select var in ... ; do

 break

done

.... now $var can be used ....

下面是一个例子:

#!/bin/sh

echo "What is your favourite OS?"

select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do

    break

done

echo "You have selected $var"



  下面是该脚本运行的结果:



What is your favourite OS?

1) Linux

2) Gnu Hurd

3) Free BSD

4) Other

#? 1

You have selected Linux





  您也可以在shell中使用如下的loop表达式:



while ...; do

....

done



 
 while-loop 将运行直到表达式测试为真。will run while the expression that we test for
is true. 关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。



  for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:



for var in ....; do

 ....

done



  在下面的例子中,将分别打印ABC到屏幕上:



#!/bin/sh

for var in A B C ; do

 echo "var is $var"

done





  下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:



#!/bin/sh

# list a content summary of a number of RPM packages

# USAGE: showrpm rpmfile1 rpmfile2 ...

# EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm

for rpmpackage in $*; do

 if [ -r "$rpmpackage" ];then

  echo "=============== $rpmpackage =============="

  rpm -qi -p $rpmpackage

 else

  echo "ERROR: cannot read file $rpmpackage"

 fi

done



  这里出现了第二个特殊的变量$*,该变量包含了所有输入的命令行参数值。如果您运行showrpm openssh.rpm w3m.rpm webgrep.rpm



  此时 $* 包含了 3 个字符串,即openssh.rpm, w3m.rpm and webgrep.rpm.



引号



 
 在向程序传递任何参数之前,程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通配符(比如*)替换成合适的文件名,它变量替换成变量值。为了防止
程序作这种替换,您可以使用引号:让我们来看一个例子,假设在当前目录下有一些文件,两个jpg文件, mail.jpg 和tux.jpg。



#!/bin/sh

echo *.jpg





  这将打印出"mail.jpg tux.jpg"的结果。



  引号 (单引号和双引号) 将防止这种通配符扩展:



#!/bin/sh

echo "*.jpg"

echo '*.jpg'



  这将打印"*.jpg" 两次。



  单引号更严格一些。它可以防止任何变量扩展。双引号可以防止通配符扩展但允许变量扩展。



#!/bin/sh

echo $SHELL

echo "$SHELL"

echo '$SHELL'



  运行结果为:



/bin/bash

/bin/bash

$SHELL



  最后,还有一种防止这种扩展的方法,那就是使用转义字符——反斜杆:



echo *.jpg

echo $SHELL



  这将输出:



*.jpg

$SHELL

Here documents



 
 当要将几行文字传递给一个命令时,here
documents(译者注:目前还没有见到过对该词适合的翻译)一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个
here documents就不必用echo函数一行行输出。 一个 "Here document" 以 &lt;<
开头,后面接上一个字符串,这个字符串还必须出现在here
document的末尾。下面是一个例子,在该例子中,我们对多个文件进行重命名,并且使用here documents打印帮助:



#!/bin/sh

# we have less than 3 arguments. Print the help text:

if [ $# -lt 3 ] ; then

cat &lt; ren -- renames a number of files using sed regular expressions



USAGE: ren 'regexp' 'replacement' files...



EXAMPLE: rename all *.HTM files in *.html:

 ren 'HTM


HELP

 exit 0

fi

OLD="$1"

NEW="$2"

# The shift command removes one argument from the list of

# command line arguments.

shift

shift

# $* contains now all the files:

for file in $*; do

  if [ -f "$file" ] ; then

   newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`

   if [ -f "$newfile" ]; then

    echo "ERROR: $newfile exists already"

   else

    echo "renaming $file to $newfile ..."

    mv "$file" "$newfile"

   fi

  fi

done



 
 这是一个复杂一些的例子。让我们详细讨论一下。第一个if表达式判断输入命令行参数是否小于3个 (特殊变量$# 表示包含参数的个数)
。如果输入参数小于3个,则将帮助文字传递给cat命令,然后由cat命令将其打印在屏幕上。打印帮助文字后程序退出。
如果输入参数等于或大于3个,我们就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。下一步,我们使用shift命令将第一个和第二个参数从
参数列表中删除,这样原来的第三个参数就成为参数列表$*的第一个参数。然后我们开始循环,命令行参数列表被一个接一个地被赋值给变量$file。接着我
们判断该文件是否存在,如果存在则通过sed命令搜索和替换来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的目
的:得到了旧文件名和新文件名。然后使用mv命令进行重命名。



函数



  如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相同的代码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:



functionname()

{

# inside the body $1 is the first argument given to the function

# $2 the second ...

body

}



  您需要在每个程序的开始对函数进行声明。



  下面是一个叫做xtitlebar的脚本,使用这个脚本您可以改变终端窗口的名称。这里使用了一个叫做help的函数。正如您可以看到的那样,这个定义的函数被使用了两次。



#!/bin/sh

# vim: set sw=4 ts=4 et:



help()

{

  cat &lt; xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole



USAGE: xtitlebar [-h] "string_for_titelbar"



OPTIONS: -h help text



EXAMPLE: xtitlebar "cvs"



HELP

  exit 0

}



# in case of error or if -h is given we call the function help:

[ -z "$1" ] && help

[ "$1" = "-h" ] && help



# send the escape sequence to change the xterm titelbar:

echo -e "33]0;$107"

#



  在脚本中提供帮助是一种很好的编程习惯,这样方便其他用户(和您)使用和理解脚本。



命令行参数



 
 我们已经见过$* 和 $1, $2 ... $9
等特殊变量,这些特殊变量包含了用户从命令行输入的参数。迄今为止,我们仅仅了解了一些简单的命令行语法(比如一些强制性的参数和查看帮助的-h选项)。
但是在编写更复杂的程序时,您可能会发现您需要更多的自定义的选项。通常的惯例是在所有可选的参数之前加一个减号,后面再加上参数值 (比如文件名)。




  有好多方法可以实现对输入参数的分析,但是下面的使用case表达式的例子无遗是一个不错的方法。



#!/bin/sh

help()

{

 cat &lt; This is a generic command line parser demo.

USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2

HELP

 exit 0

}



while [ -n "$1" ]; do

case $1 in

  -h) help;shift 1;; # function help is called

  -f) opt_f=1;shift 1;; # variable opt_f is set

  -l) opt_l=$2;shift 2;; # -l takes an argument -&gt; shift by 2

  --) shift;break;; # end of options

  -*) echo "error: no such option $1. -h for help";exit 1;;

  *) break;;

esac

done



echo "opt_f is $opt_f"

echo "opt_l is $opt_l"

echo "first arg is $1"

echo "2nd arg is $2"





  您可以这样运行该脚本:



cmdparser -l hello -f -- -somefile1 somefile2





  返回的结果是:



opt_f is 1

opt_l is hello

first arg is -somefile1

2nd arg is somefile2





  这个脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,首先输入的应该是包含减号的参数。



实例



  一般编程步骤



  现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:



cp framework.sh myscript



  然后再插入自己的函数。



  让我们再看两个例子:



  二进制到十进制的转换



  脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:



#!/bin/sh

# vim: set sw=4 ts=4 et:

help()

{

 cat &lt; b2h -- convert binary to decimal



USAGE: b2h [-h] binarynum



OPTIONS: -h help text



EXAMPLE: b2h 111010

will return 58

HELP

 exit 0

}



error()

{

  # print an error and exit

  echo "$1"

  exit 1

}



lastchar()

{

  # return the last character of a string in $rval

  if [ -z "$1" ]; then

    # empty string

    rval=""

    return

  fi

  # wc puts some space behind the output this is why we need sed:

  numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `

  # now cut out the last char

  rval=`echo -n "$1" | cut -b $numofchar`

}



chop()

{

  # remove the last character in string and return it in $rval

  if [ -z "$1" ]; then

    # empty string

    rval=""

    return

  fi

  # wc puts some space behind the output this is why we need sed:

  numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `

  if [ "$numofchar" = "1" ]; then

    # only one char in string

    rval=""

    return

  fi

  numofcharminus1=`expr $numofchar "-" 1`

  # now cut all but the last char:

  rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`

}





while [ -n "$1" ]; do

case $1 in

  -h) help;shift 1;; # function help is called

  --) shift;break;; # end of options

  -*) error "error: no such option $1. -h for help";;

  *) break;;

esac

done



# The main program

sum=0

weight=1

# one arg must be given:

[ -z "$1" ] && help

binnum="$1"

binnumorig="$1"



while [ -n "$binnum" ]; do

  lastchar "$binnum"

  if [ "$rval" = "1" ]; then

    sum=`expr "$weight" "+" "$sum"`

  fi

  # remove the last position in $binnum

  chop "$binnum"

  binnum="$rval"

  weight=`expr "$weight" "*" 2`

done



echo "binary $binnumorig is decimal $sum"

#



  该脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制"10"可以这样转换成十进制:



0 * 1 + 1 * 2 = 2



  为了得到单个的二进制数我们是用了lastchar 函数。该函数使用wc –c计算字符个数,然后使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符。



  文件循环程序



 
 或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月以后,这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的脚
本rotatefile
可以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而对于outmail.1就变成了outmail.2
等等等等...



#!/bin/sh

# vim: set sw=4 ts=4 et:

ver="0.1"

help()

{

  cat &lt; rotatefile -- rotate the file name



USAGE: rotatefile [-h] filename



OPTIONS: -h help text



EXAMPLE: rotatefile out

This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1

and create an empty out-file



The max number is 10



version $ver

HELP

  exit 0

}



error()

{

  echo "$1"

  exit 1

}

while [ -n "$1" ]; do

case $1 in

  -h) help;shift 1;;

  --) break;;

  -*) echo "error: no such option $1. -h for help";exit 1;;

  *) break;;

esac

done



# input check:

if [ -z "$1" ] ; then

error "ERROR: you must specify a file, use -h for help"

fi

filen="$1"

# rename any .1 , .2 etc file:

for n in 9 8 7 6 5 4 3 2 1; do

  if [ -f "$filen.$n" ]; then

    p=`expr $n + 1`

    echo "mv $filen.$n $filen.$p"

    mv $filen.$n $filen.$p

  fi

done

# rename the original file:

if [ -f "$filen" ]; then

  echo "mv $filen $filen.1"

  mv $filen $filen.1

fi

echo touch $filen

touch $filen



  这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个9到1的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名为文件1同时建立一个与原始文件同名的空文件。



调试



  最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间。



  shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误,您可以这样来进行调试:



sh -x strangescript





  这将执行该脚本并显示所有变量的值。



  shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:



sh -n your_script





  这将返回所有语法错误。




Powered by ScribeFire.

'html' *.HTM



HELP

 exit 0

fi

OLD="$1"

NEW="$2"

# The shift command removes one argument from the list of

# command line arguments.

shift

shift

# $* contains now all the files:

for file in $*; do

  if [ -f "$file" ] ; then

   newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`

   if [ -f "$newfile" ]; then

    echo "ERROR: $newfile exists already"

   else

    echo "renaming $file to $newfile ..."

    mv "$file" "$newfile"

   fi

  fi

done



 
 这是一个复杂一些的例子。让我们详细讨论一下。第一个if表达式判断输入命令行参数是否小于3个 (特殊变量$# 表示包含参数的个数)
。如果输入参数小于3个,则将帮助文字传递给cat命令,然后由cat命令将其打印在屏幕上。打印帮助文字后程序退出。
如果输入参数等于或大于3个,我们就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。下一步,我们使用shift命令将第一个和第二个参数从
参数列表中删除,这样原来的第三个参数就成为参数列表$*的第一个参数。然后我们开始循环,命令行参数列表被一个接一个地被赋值给变量$file。接着我
们判断该文件是否存在,如果存在则通过sed命令搜索和替换来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的目
的:得到了旧文件名和新文件名。然后使用mv命令进行重命名。



函数



  如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相同的代码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:



functionname()

{

# inside the body $1 is the first argument given to the function

# $2 the second ...

body

}



  您需要在每个程序的开始对函数进行声明。



  下面是一个叫做xtitlebar的脚本,使用这个脚本您可以改变终端窗口的名称。这里使用了一个叫做help的函数。正如您可以看到的那样,这个定义的函数被使用了两次。



#!/bin/sh

# vim: set sw=4 ts=4 et:



help()

{

  cat &lt; xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole



USAGE: xtitlebar [-h] "string_for_titelbar"



OPTIONS: -h help text



EXAMPLE: xtitlebar "cvs"



HELP

  exit 0

}



# in case of error or if -h is given we call the function help:

[ -z "$1" ] && help

[ "$1" = "-h" ] && help



# send the escape sequence to change the xterm titelbar:

echo -e "33]0;$107"

#



  在脚本中提供帮助是一种很好的编程习惯,这样方便其他用户(和您)使用和理解脚本。



命令行参数



 
 我们已经见过$* 和 $1, $2 ... $9
等特殊变量,这些特殊变量包含了用户从命令行输入的参数。迄今为止,我们仅仅了解了一些简单的命令行语法(比如一些强制性的参数和查看帮助的-h选项)。
但是在编写更复杂的程序时,您可能会发现您需要更多的自定义的选项。通常的惯例是在所有可选的参数之前加一个减号,后面再加上参数值 (比如文件名)。




  有好多方法可以实现对输入参数的分析,但是下面的使用case表达式的例子无遗是一个不错的方法。



#!/bin/sh

help()

{

 cat &lt; This is a generic command line parser demo.

USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2

HELP

 exit 0

}



while [ -n "$1" ]; do

case $1 in

  -h) help;shift 1;; # function help is called

  -f) opt_f=1;shift 1;; # variable opt_f is set

  -l) opt_l=$2;shift 2;; # -l takes an argument -&gt; shift by 2

  --) shift;break;; # end of options

  -*) echo "error: no such option $1. -h for help";exit 1;;

  *) break;;

esac

done



echo "opt_f is $opt_f"

echo "opt_l is $opt_l"

echo "first arg is $1"

echo "2nd arg is $2"





  您可以这样运行该脚本:



cmdparser -l hello -f -- -somefile1 somefile2





  返回的结果是:



opt_f is 1

opt_l is hello

first arg is -somefile1

2nd arg is somefile2





  这个脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,首先输入的应该是包含减号的参数。



实例



  一般编程步骤



  现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:



cp framework.sh myscript



  然后再插入自己的函数。



  让我们再看两个例子:



  二进制到十进制的转换



  脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:



#!/bin/sh

# vim: set sw=4 ts=4 et:

help()

{

 cat &lt; b2h -- convert binary to decimal



USAGE: b2h [-h] binarynum



OPTIONS: -h help text



EXAMPLE: b2h 111010

will return 58

HELP

 exit 0

}



error()

{

  # print an error and exit

  echo "$1"

  exit 1

}



lastchar()

{

  # return the last character of a string in $rval

  if [ -z "$1" ]; then

    # empty string

    rval=""

    return

  fi

  # wc puts some space behind the output this is why we need sed:

  numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `

  # now cut out the last char

  rval=`echo -n "$1" | cut -b $numofchar`

}



chop()

{

  # remove the last character in string and return it in $rval

  if [ -z "$1" ]; then

    # empty string

    rval=""

    return

  fi

  # wc puts some space behind the output this is why we need sed:

  numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `

  if [ "$numofchar" = "1" ]; then

    # only one char in string

    rval=""

    return

  fi

  numofcharminus1=`expr $numofchar "-" 1`

  # now cut all but the last char:

  rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`

}





while [ -n "$1" ]; do

case $1 in

  -h) help;shift 1;; # function help is called

  --) shift;break;; # end of options

  -*) error "error: no such option $1. -h for help";;

  *) break;;

esac

done



# The main program

sum=0

weight=1

# one arg must be given:

[ -z "$1" ] && help

binnum="$1"

binnumorig="$1"



while [ -n "$binnum" ]; do

  lastchar "$binnum"

  if [ "$rval" = "1" ]; then

    sum=`expr "$weight" "+" "$sum"`

  fi

  # remove the last position in $binnum

  chop "$binnum"

  binnum="$rval"

  weight=`expr "$weight" "*" 2`

done



echo "binary $binnumorig is decimal $sum"

#



  该脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制"10"可以这样转换成十进制:



0 * 1 + 1 * 2 = 2



  为了得到单个的二进制数我们是用了lastchar 函数。该函数使用wc –c计算字符个数,然后使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符。



  文件循环程序



 
 或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月以后,这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的脚
本rotatefile
可以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而对于outmail.1就变成了outmail.2
等等等等...



#!/bin/sh

# vim: set sw=4 ts=4 et:

ver="0.1"

help()

{

  cat &lt; rotatefile -- rotate the file name



USAGE: rotatefile [-h] filename



OPTIONS: -h help text



EXAMPLE: rotatefile out

This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1

and create an empty out-file



The max number is 10



version $ver

HELP

  exit 0

}



error()

{

  echo "$1"

  exit 1

}

while [ -n "$1" ]; do

case $1 in

  -h) help;shift 1;;

  --) break;;

  -*) echo "error: no such option $1. -h for help";exit 1;;

  *) break;;

esac

done



# input check:

if [ -z "$1" ] ; then

error "ERROR: you must specify a file, use -h for help"

fi

filen="$1"

# rename any .1 , .2 etc file:

for n in 9 8 7 6 5 4 3 2 1; do

  if [ -f "$filen.$n" ]; then

    p=`expr $n + 1`

    echo "mv $filen.$n $filen.$p"

    mv $filen.$n $filen.$p

  fi

done

# rename the original file:

if [ -f "$filen" ]; then

  echo "mv $filen $filen.1"

  mv $filen $filen.1

fi

echo touch $filen

touch $filen



  这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个9到1的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名为文件1同时建立一个与原始文件同名的空文件。



调试



  最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间。



  shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误,您可以这样来进行调试:



sh -x strangescript





  这将执行该脚本并显示所有变量的值。



  shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:



sh -n your_script





  这将返回所有语法错误。



Powered by ScribeFire.

Thursday 21 June 2007

使用VMware虚拟磁盘管理工具 [原][译+]

VMware虚拟磁盘管理工具是VMware Workstation软件包里的一个软件,它让你用命令行或通过脚本来创建管理修改虚拟磁盘文 件。它的一个重要的特性是能够增大虚拟磁盘大小,使虚拟磁盘的最大尺寸比刚创建时(定义的)更大。它是这样一种方法,如果你需要更多的磁盘空间在已经定义 的虚拟机中,而你又不想添加另外一块硬盘或者用Ghost软件来传递虚拟磁盘上的数据到另外一块更大的虚拟磁盘上去时,你可以用改变虚拟磁盘最大尺寸方法 来做。不过你可不能用这种方法对你的物理硬盘实施。
另外一个功能是让你能够改变虚拟磁盘的类型。当你创建虚拟机时,你定义了虚拟磁盘空间的分配方式。你可以在以下选择一种分配方式:
- 所有的虚拟磁盘空间预分配。它相当于虚拟磁盘管理工具所说的预分配磁盘类型。
- 虚拟磁盘在开始时最小随着数据的增加而变大。它相当于虚拟磁盘管理工具所说的可增长磁盘类型。
使 用虚拟磁盘管理工具,你能够更改虚拟磁盘的类型为预分配或可增长的、单个文件储存或每个文件大小为2GB的多文件方式。举个例子,你可以分配所有的虚拟磁 盘空间,然后发现你需要收回一些主机上的硬盘空间。你能转换预分配的虚拟磁盘为可增长的虚拟磁盘,然后删除原来的那个虚拟磁盘文件。(这样)虚拟磁盘的大 小将随着你的数据的增长而增长。
这些功能和使用脚本自动管理虚拟磁盘方法在VMware Workstation5.0版本中提供。
你能够用虚拟磁盘管理工具完成以下任务:
- 使用脚本自动管理虚拟磁盘。
- 创建虚拟磁盘而不和任何一个虚拟机关联,举个例子,创建它作为样板。
- 在预分配和可增长的虚拟磁盘类型间进行转换。当你更改为可增长的虚拟磁盘类型,你就能够收回一些磁盘空间。你也能通过收缩虚拟磁盘来收回更多的空间。
- 增大虚拟磁盘的尺寸,使它比你创建时定义的尺寸更大。
- 磁盘碎片整理虚拟磁盘。
- 准备和收缩虚拟磁盘而不需要开启虚拟机进行(仅适用于Windows宿主机)。
你可以用虚拟磁盘管理程序管理由VMware GSX Server, VMware Workstation and VMware VirtualCenter(由GSX Server提供被VirtualCenter管理的虚拟磁盘)创建的虚拟磁盘。
注意:你不能用虚拟磁盘工具创建物理磁盘。物理磁盘不能被虚拟磁盘管理工具或Workstation软件收缩。
更多关于使用虚拟磁盘工具的信息,请阅读以下章节:
- 使用虚拟磁盘管理软件
- 使用虚拟磁盘管理实例

使用虚拟磁盘管理软件
打开宿主机中的命令行或终端(Linux中的命令行),以运行虚拟磁盘管理软件。在Windows宿主机中,更改目录为你安装Workstation软件 所在的目录。默认的安装目录为C:\Program Files\VMware\VMware Workstation。
screen.width/2)this.style.width=screen.width/2;" border="0">

命令语法:
vmware-vdiskmanager [选项]
这里的选项你必须包含以下的一些选择项或参数
选项和参数
描述

虚拟磁盘文件的名字。虚拟磁盘文件必须是.vmdk为扩展名。你能够指定一个你想要储存的虚拟磁盘文件的路径。如果你在你的宿主机中映射了网络共享,你也可以提供确切的虚拟磁盘文件的路径信息来创建虚拟磁盘在这个网络共享中

-c
创建虚拟磁盘。你必须用-a, -s 和 -t 并指定选项参数,然后你需要指定所要创建的虚拟磁盘文件的文件名。

-r
转换已经指定类型的虚拟磁盘的类型,结果会输出创建一个新的虚拟磁盘。你必须用-t选项来指定你想要转换成的磁盘类型,并且指定目标虚拟磁盘的文件名。
一旦转换完成,你可以先测试虚拟磁盘以确保它能够像你所希望的那样工作,然后再删除原来的那个虚拟磁盘文件。
为了让虚拟机重新认识转换后的虚拟磁盘,你应该使用虚拟机设置编辑器先从虚拟机中移除先前存在的虚拟磁盘,然后添加转换好的虚拟磁盘给虚拟机。

-x [GB|MB]
增大虚拟磁盘到指定的容量。你必须指定新的更大尺寸的虚拟磁盘用GB或MB单位标示。你不能改变物理磁盘的大小。(废话)
注意:在你运行虚拟磁盘管理软件前,你应该先备份虚拟磁盘文件。(因为不会创建新的文件,所以备份以防增大磁盘操作失败)

-d
对指定的虚拟磁盘碎片整理。你只能磁盘碎片整理可增长的虚拟磁盘。你不能磁盘碎片整理预分配的虚拟磁盘。

-p
为收缩磁盘做准备处理。如果虚拟磁盘被分成多个分区,每个分区必须被单独准备。分区(比如C:或D:)必须用VMware DiskMount工具映射。 更多的应用VMware DiskMount映射和解除虚拟磁盘的映射的内容,请看VMware DiskMount用户手册,可以在VMware站点中::URL::http://www.vmware.com/pdf/VMwareDiskMount.pdf 下载到。VMware DiskMount免费软件也可以在::URL::http://www.vmware.com/download/ws/ 页面下载到。
在你对分区准备处理后,解除对此分区的映射。继续映射虚拟磁盘的其他每个分区,为收缩磁盘作准备处理直到完成虚拟磁盘上的所有分区的准备工作。
你在同一时刻只能用VMware DiskMount映射虚拟磁盘的一个分区。你仅仅能在Windows宿主机上进行虚拟磁盘的收缩分区准备工作。

-k
收缩指定的虚拟磁盘。你只能够收缩可增长磁盘。你只能在Windows宿主机中(用这种方法)收缩虚拟磁盘。
你不能够收缩有虚拟机快照的虚拟磁盘。你可以保持现有虚拟磁盘的状态,而用快照管理器删除所有快照。你也可以放弃自快照以来对虚拟磁盘所做的更改,恢复到快照时状态。

-a [ ide | buslogic | lsilogic ]
指定磁盘适配器的类型。你在创建新的虚拟磁盘时必须指定其类型。选择以下类型之一:
ide —— IDE接口适配器
buslogic —— BusLogic SCSI接口适配器
lsilogic —— LSI Logic SCSI接口适配器

-s [GB|MB]
指定虚拟磁盘的大小。确定大小用GB或MB做单位。你必须在创建磁盘时指定其大小。
尽管你必须指定虚拟磁盘的大小,但当你增长它的大小时,你不能用-s这个选项。
可以指定的磁盘大小规定:IDE和SCSI适配器都为最小100MB,最大950GB。

-t [0|1|2|3]
你在创建一个新的虚拟磁盘或者重新配置一个虚拟磁盘时必须指定虚拟磁盘的类型。指定以下类型之一:
0 —— 创建一个包含在单一虚拟文件中的可增长虚拟磁盘
1 —— 创建一个被分割为每个文件2GB大小的可增长虚拟磁盘
2 —— 创建一个包含在单一虚拟文件中的预分配虚拟磁盘
3 —— 创建一个被分割为每个文件2GB大小的预分配虚拟磁盘

-q
禁止虚拟磁盘管理程序写日志
如果你允许记录日志,日志将会被虚拟磁盘管理程序产生并储存。在虚拟磁盘管理程序运行后,日志的名字和存放位置将会出现在命令行或终端中。

-n
重命名指定的虚拟磁盘。需要指定命名后的虚拟磁盘名字。

使用VMware虚拟磁盘管理工具实例
以下例子描述怎样使用虚拟磁盘管理工具。你需要在命令行中运行虚拟磁盘管理工具。

创建虚拟磁盘
命令:vmware-vdiskmanager -c -t 0 -s 40GB -a ide myDisk.vmdk
这个命令将创建一个40GB大小IDE接口的名字为myDisk的虚拟硬盘。虚拟磁盘包含在一个单一文件中。这个虚拟磁盘没有被预分配磁盘空间。
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -c -s 40Gb –a ide -t 0 E:\myDisk.vmdk
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
Creating a monolithic growable disk 'E:\myDisk.vmdk'
Virtual disk creation successful.

转换一个虚拟磁盘
转换一个预分配虚拟磁盘为可增长虚拟磁盘,用以下这个命令:
vmware-vdiskmanager -r sourceDisk.vmdk -t 0 targetDisk.vmdk
这个命令将转换磁盘从它的原始的预分配模式转变为包含在单一文件中的可增长虚拟磁盘。这个虚拟磁盘空间将不会被预先分配,虚拟磁盘工具将收回虚拟磁盘中的一些磁盘空间,而仅仅让里面的数据占用虚拟磁盘空间。
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -r "D:\WinXP
SP2 V2.5\Windows XP Professional.vmdk" -t 0 "L:\Windows XP Professional.vmdk"
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
Creating a monolithic growable disk 'L:\Windows XP Professional.vmdk'
Convert: 100% done.
Virtual disk conversion successful.

增大存在的虚拟磁盘的大小
命令:vmware-vdiskmanager -x 40GB myDisk.vmdk
这条命令将把虚拟磁盘myDisk.vmdk大小增大到40GB
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -x 40GB "D:\WinXP SP2 V2.5\Windows XP Professional S.vmdk"
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
Grow: 100% done.
The old geometry C/H/S of the disk is: 8322/16/63
The new geometry C/H/S of the disk is: 16383/16/63
Disk expansion completed successfully.
WARNING: If the virtual disk is partitioned, you must use a third-party
utility in the virtual machine to expand the size of the
partitions. For more information, see:
::URL::http://www.vmware.com/support/kb/enduser/std_adp.php?p_faqid=1647
创建好后,可以在磁盘管理中,看到未指派的空间。如果你想扩大磁盘分区的大小,可以用其他第三方软件来做。
screen.width/2)this.style.width=screen.width/2;" border="0">

举例用第三方磁盘管理软件PartitionMagic来调整分区大小
原始磁盘
screen.width/2)this.style.width=screen.width/2;" border="0">

进入调整向导
screen.width/2)this.style.width=screen.width/2;" border="0">

经过设置后的调整方案
screen.width/2)this.style.width=screen.width/2;" border="0">

应用方案后的结果
screen.width/2)this.style.width=screen.width/2;" border="0">

主磁盘C空间从4GB变为了10GB。

重命名虚拟磁盘
重命名虚拟磁盘,首先把虚拟磁盘从虚拟机中移除。(选择 虚拟机 )设置 〉虚拟磁盘,然点移除按钮)
然后重命名命令:vmware-vdiskmanager -n myDisk.vmdk myNewDisk.vmdk
重命名磁盘定位在不同的目录下的命令:
vmware-vdiskmanager -n myDisk.vmdk ..\\myNewDisk.vmdk
注意:这是一个在windows宿主机中的路径方式。
定位在不同目录下,但保持相同名字的虚拟磁盘命令:
vmware-vdiskmanager -n myDisk.vmdk ..\\myDisk.vmdk
在你重命名或重定位虚拟磁盘后,把虚拟磁盘添加回虚拟机中使用。选择 虚拟机 〉设置,点添加,然后根据向导添加这个已经存在的虚拟磁盘。
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -n "D:\WinXP SP2 V2.5\Windows XP Professional S.vmdk" "D:\WinXP SP2 V2.5\Windows XP Professio nal WS.vmdk"
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
Renaming completed successfully.
重命名几乎是瞬间完成的,虽然如此,不过我用MD5验证前后的.vmdk文件,证实文件确实经过了内部修改,得到了不同的MD5码。

磁盘碎片整理虚拟磁盘
命令:vmware-vdiskmanager -d myDisk.vmdk
记住,你不能磁盘碎片整理预分配的虚拟磁盘。你也不能用这条命令磁盘碎片整理物理硬盘。(废话)
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -d "D:\WinXP SP2 V2.5\Windows XP Professional S.vmdk"
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
Defragment: 100% done.
Defragmentation completed successfully.

为收缩虚拟磁盘做准备
命令:vmware-vdiskmanager –p S:
一旦准备完成,解除分区映射。重复这个过程在虚拟磁盘的每个分区上。(这样可以得到最好的收缩效果)在你为收缩磁盘准备好了所有分区后,你就可以收缩虚拟磁盘了
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -p S:
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
100% wiping done.
我所映射的虚拟磁盘S
screen.width/2)this.style.width=screen.width/2;" border="0">

收缩虚拟磁盘
(这种方法)收缩虚拟磁盘必须在Windows宿主机下进行。在你收缩虚拟磁盘以前,确保你已经为虚拟磁盘的所有分区进行了收缩准备。
命令:vmware-vdiskmanager -k myDisk.vmdk
记住,你不能收缩预分配的磁盘。你也不能收缩物理磁盘。如果虚拟磁盘有快照,你也不能收缩。在你收缩以前删除所有的快照。
实际命令输入:
D:\Big Program Files\VMware\VMware Workstation>vmware-vdiskmanager -k "D:\WinXP SP2 V2.5\Windows XP Professional S.vmdk"
执行结果显示:
Using log file C:\DOCUME~1\AnEgg\LOCALS~1\Temp\vmware-AnEgg\vdiskmanager.log
Shrink: 100% done.
Shrink completed successfully.
收缩磁盘时会产生一个临时文件,其实它就是收缩后的虚拟磁盘文件,会代替原来的那个虚拟磁盘文件。
screen.width/2)this.style.width=screen.width/2;" border="0">

(以上操作我都尝试过,并在虚拟机中验证可行,虚拟机和虚拟磁盘运行并没有受到任何的影响。)

附上命令行中的虚拟磁盘管理工具的帮助
screen.width/2)this.style.width=screen.width/2;" border="0">

Ubuntu的init方式

如下是一个不被推荐使用的命令update-rc.d,但是其中介绍了linux的service启动顺序和原理.

关于runlevel N和/etc/rcN.d的关系.

------------------------------------------
只要进入rc3.d 更改gdm前面的s为k,这样,当再init 3的时候,就和fedora效果一样,进入text command界面.

如果要修改默认runlevel,更改/etc/event.d/rc-default.d,在最后一行加入你想要的runLEVEL,比如:telinit 3
------------------------------------------

###################################################

UPDATE-RC.D(8) sysv-rc UPDATE-RC.D(8)







NAME

update-rc.d - install and remove System-V style init script links



SYNOPSIS

update-rc.d [-n] [-f] name remove



update-rc.d [-n] name defaults|multiuser [NN | SS KK]



update-rc.d [-n] name start|stop NN runlevel [runlevel]... .

start|stop NN runlevel [runlevel]... . ...



DESCRIPTION

update-rc.d updates the System V style init script links /etc/rcrun‐

level.d/NNname whose target is the script /etc/init.d/name. These

links are run by init when it changes runlevels; they are generally

used to start and stop system services such as daemons. runlevel is

one of the runlevels supported by init, namely, 0123456789S, and NN is

the two-digit sequence number that determines where in the sequence

init will run the scripts.



This manpage documents only the usage and behaviour of update-rc.d.

For a discussion of the System V style init script arrangements please

see init(8) and the Debian Policy Manual.



Please note that this program was designed for use in package main‐

tainer scripts and, accordingly, has only the very limited functional‐

ity required by such scripts. System administrators are not encouraged

to use update-rc.d to manage runlevels. They should edit the links

directly or use runlevel editors such as sysv-rc-conf and bum instead.



INSTALLING INIT SCRIPT LINKS

When run with either the defaults, multiuser, start, or stop options,

update-rc.d makes links /etc/rcrunlevel.d/[SK]NNname that point to the

script /etc/init.d/name.



If any files /etc/rcrunlevel.d/[SK]??name already exist then update-

rc.d does nothing. The program was written this way so that it will

never change an existing configuration, which may have been customized

by the system administrator. The program will only install links if

none are present, i.e., if it appears that the service has never been

installed before.



A common system administration error is to delete the links with the

thought that this will "disable" the service, i.e., that this will pre‐

vent the service from being started. However, if all links have been

deleted then the next time the package is upgraded, the package’s

postinst script will run update-rc.d again and this will reinstall

links at their factory default locations. The correct way to disable

services is to configure the service as stopped in all runlevels in

which it is started by default. In the System V init system this means

renaming the service’s symbolic links from S to K.



If defaults is used then update-rc.d will make links to start the ser‐

vice in runlevels 2345 and to stop the service in runlevels 016. If

multiuser is used then update-rc.d will make links to start the service

in runlevels 2345 and top stop the service in only runlevel 1. By

default all the links will have sequence number 20, but this can be

overridden by supplying one NN or two SS and KK arguments to either

defaults or multiuser; a single argument overrides the sequence number

for both start and stop links whereas a pair of arguments overrides the

sequence numbers for start and stop links, respectively.



As a rule of thumb, the sequence number of the stop link should 100

minus the sequence number of the start link; this causes services to be

stopped in the opposite order to that in which they are started. Obvi‐

ously, therefore, the default stop sequence number should be 80.

Defaulting to 20, as update-rc.d does, is an old bug that cannot be

fixed because of the risk of breaking things.



Instead of defaults or multiuser one can give one or more sets of argu‐

ments specifying particular runlevels in which to start or stop the

service. Each of these sets of arguments starts with the keyword start

or stop and a sequence number NN, followed by one or more runlevel num‐

bers. The set is terminated by a solitary full stop character. When

explicit specification, rather than defaults, is used there will usu‐

ally be one start and one stop set. If different sequence codes are

required in different runlevels then several start sets or several stop

sets may be specified. If this is done and the same runlevel is named

in multiple sets then only the last one counts. Therefore it is not

possible to create multiple start or multiple stop links for a service

in a single runlevel directory.



The script /etc/init.d/name must exist before update-rc.d is run to

create the links.



REMOVING SCRIPTS

When invoked with the remove option, update-rc.d removes any links in

the /etc/rcrunlevel.d directories to the script /etc/init.d/name. The

script must have been deleted already. If the script is still present

then update-rc.d aborts with an error message.



update-rc.d is usually called from a package’s post-removal script when

that script is given the purge argument. Any files in the /etc/rcrun‐

level.d directories that are not symbolic links to the script

/etc/init.d/name will be left untouched.





OPTIONS

-n Don’t do anything, just show what we would do.



-f Force removal of symlinks even if /etc/init.d/name still exists.



EXAMPLES

Insert links using the defaults:

update-rc.d foobar defaults

Equivalent command using explicit argument sets:

update-rc.d foobar start 20 2 3 4 5 . stop 20 0 1 6 .

Insert links for a service that should be running during multi-user

mode, but that does not need to be explicitly stopped on shutdown:

update-rc.d foobar multiuser

Equivalent command using explicit argument sets:

update-rc.d foobar start 20 2 3 4 5 . stop 20 1 .

More typical command using explicit argument sets:

update-rc.d foobar start 30 2 3 4 5 . stop 70 0 1 6 .

Remove all links for a script (assuming foobar has been deleted

already):

update-rc.d foobar remove

Example of disabling a service:

update-rc.d -f foobar remove

update-rc.d foobar stop 20 2 3 4 5 .

Example of a command for installing a system initialization-and-shut‐

down script:

update-rc.d foobar start 45 S . start 31 0 6 .

Example of a command for disabling a system initialization-and-shutdown

script:

update-rc.d -f foobar remove

update-rc.d foobar stop 45 S .





NOTES

The multiuser option is an Ubuntu-extension intended to reduce the

amount of time spent stopping services during shutdown and reboot that

have no particular requirement to be explicitly stopped.



Unless your init script does something in the stop command that is more

than just sending the TERM or KILL signal to the running process, you

should strongly consider using multiuser instead of defaults.





BUGS

See http://bugs.debian.org/sysv-rc.



FILES

/etc/init.d/

The directory containing the actual init scripts.



/etc/rc?.d/

The directories containing the links used by init and managed by

update-rc.d.



/etc/init.d/skeleton

Model for use by writers of init.d scripts.



SEE ALSO

Debian Policy Manual,

/etc/init.d/skeleton,

sysv-rc-conf(8), bum(8), init(8).







Debian Project 14 November 2005 UPDATE-RC.D(8)



Wednesday 20 June 2007

Repository - Ubuntu 7.04

repository:1.official version. 2.stable repos from next version(careful). 3.3rd parties(mediaubuntu,debuntu)



#################################################################################

## Debuntu 7.04 "Feisty Fawn"
deb http://repository.debuntu.org/ feisty multiverse
deb-src http://repository.debuntu.org/ feisty multiverse
# sudo wget http://repository.debuntu.org/GPG-Key-chantra.txt -O- | sudo apt-key add -

## MediaUbuntu 7.04 "Feisty Fawn"

deb http://packages.medibuntu.org/ feisty free non-free

# sudo wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add -


#########################################
#### Official/Supported Ubuntu Repos for 7.04 ####
#########################################

#### Main ####
deb http://archive.ubuntu.com/ubuntu/ feisty main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ feisty main restricted universe multiverse

#### Updates #####
deb http://archive.ubuntu.com/ubuntu/ feisty-updates main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ feisty-updates main restricted universe multiverse

#### Backports ####
deb http://archive.ubuntu.com/ubuntu/ feisty-backports main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu/ feisty-backports main restricted universe multiverse

#### Security Updates ####
deb http://security.ubuntu.com/ubuntu feisty-security main restricted universe multiverse
deb-src http://security.ubuntu.com/ubuntu feisty-security main restricted universe multiverse

#### Proposed Multiverse ####
deb http://archive.ubuntu.com/ubuntu feisty-proposed main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu feisty-proposed main restricted universe multiverse

#### Canonical Commercial ####
##(Hosted on Canonical servers, not Ubuntu servers. RealPlayer10, Opera and more to come.)
deb http://archive.canonical.com/ubuntu feisty-commercial main


#################################################################################
## newer versions(7.10 gutsy) of the distribution.

deb http://archive.ubuntu.com/ubuntu/ gutsy main restricted
deb-src http://archive.ubuntu.com/ubuntu/ gutsy main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://archive.ubuntu.com/ubuntu/ gutsy-updates main restricted
deb-src http://archive.ubuntu.com/ubuntu/ gutsy-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## universe WILL NOT receive any review or updates from the Ubuntu security
## team.
#deb http://archive.ubuntu.com/ubuntu/ gutsy universe
#deb-src http://archive.ubuntu.com/ubuntu/ gutsy universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
#deb http://archive.ubuntu.com/ubuntu/ gutsy multiverse
#deb-src http://archive.ubuntu.com/ubuntu/ gutsy multiverse

## Uncomment the following two lines to add software from the 'backports'
## repository.
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
#deb http://archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse
#deb-src http://archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse


-----------------------------------------------------------------------------------------------

Fedora repository:

freshrpms.net
livna.org: http://rpm.livna.org/rlowiki/

Tuesday 19 June 2007

make within linux

Some application which is MAKEd by yourself need some lib can not just install some lib from repositories, while you must install the lib before ./CONFIGURE, in this case the application will call the lib automatically when it was MAKEd.

Such as pidgin, MSN/GTALK will need SSL support, where "libnss-dev" will help. But you must install it before ./CONFIGURE!!!!!

Monday 18 June 2007

《Business 2.0》评出的2007年25大网络新锐如下:

1.www.stumbleupon.com(社交媒体)

  公司总部:旧金山

  员工人数:12人

  创建时间:2001年

  创始人:格夫·史密斯(Geoff Smith)、加里特·坎普(Garrett Camp)、贾斯丁·拉弗朗斯(Justin LaFrance)

  商业模式:广告、付费用户

  2007年目标:推出内容控制和移动视频推荐等新功能

  2.www.slide.com(社交媒体)

  公司总部:旧金山

  员工人数:45人

  创建时间:2004年

  创始人:马克斯·莱齐恩(Max Levchin)

  商业模式:广告、付费用户

  2007年目标:增加员工、进军亚洲市场、加入手机功能

  3.www.bebo.com(社交媒体)

  公司总部:旧金山

  员工人数:28人

  创建时间:2005年

  创始人:迈克尔·波奇(Michael Birch)、西奥琪·波奇(Xochi Birch)

  商业模式:广告

  2007年目标:推广Bebo作家频道、招聘销售团队

  4.www.meebo.com(社交媒体)

  员工人数:12人

  创始人:辛迪·简(Sandy Jen)、塞斯·斯特恩伯格(Seth Sternberg)、埃莱尼·维利(Elaine Wherry)

  商业模式:广告

  2007年目标:增加员工

  5.www.wikia.com(社交媒体)

  公司总部:圣马蒂奥

  员工人数:33人

  创建时间:2004年

  创始人:安吉拉·比斯利(Angela Beesley)、吉米·维尔斯(Jimmy Wales)

  商业模式:广告

  2007年目标:增加员工、进军日本市场、支持更多语言、开发开放源代码搜索引擎

  6.www.joost.com(视频)

  公司总部:卢森堡

  员工人数:100人

  创建时间:2006年

  创始人:贾努斯·弗里斯(Janus Friis)、尼克拉斯·曾特罗姆(Niklas Zennstrom)

  商业模式:广告

  2007年目标:签署更多内容协议

  7.www.dabble.com(视频)

  公司总部:伯克利

  员工人数:11人

  创建时间:2005年

  创始人:玛丽·霍德尔(Mary Hodder)

  商业模式:广告

  2007年目标:增加员工和新功能

  8.www.metacafe.com(视频)

  公司总部:帕罗阿尔托

  员工人数:65人

  创建时间:2003年

  创始人:埃里克·汉切伯格(Erick Hachenburg)

  商业模式:广告

  2007年目标:增加员工、同电影公司合作

  9.www.revision3.com(视频)

  公司总部:旧金山

  员工人数:7人

  创建时间:2005年

  创始人:杰·阿德尔森(Jay Adelson)

  商业模式:广告

  2007年目标:增加新节目

  10.www.blip.tv(视频)

  公司总部:纽约

  员工人数:12人

  创建时间:2005年

  创始人:迪纳·卡普兰(Dina Kaplan)、迈克·哈代克(Mike Hudack)

  商业模式:授权、广告

  2007年目标:增加员工

  11.www.fon.com(移动)

  公司总部:

马德里

  员工人数:90人

  创建时间:2006年

  创始人:马丁·瓦萨维斯基(Martin Varsavsky)

  商业模式:付费用户、路由器销售

  2007年目标:同美国移动通信运营商谈判

  12.www.loopt.com(移动)

  公司总部:帕罗阿尔托

  员工人数:18人

  创建时间:2005年

  创始人:萨姆·奥特曼(Sam Altman)

  商业模式:广告、付费用户

  2007年目标:同赞助商签约、同美国二级运营商谈判

  13.www.getmobio.com(移动)

  公司总部:库珀蒂诺

  员工人数:40人

  创建时间:2005年

  创始人:拉姆尼克·巴辛(Ramneek Bhasin)

  商业模式:广告

  2007年目标:推出服务

  14.www.tinypictures.com(移动)

  公司总部:旧金山

  员工人数:12人

  创建时间:2005年

  创始人:约翰·波伊森(John Poisson)

  商业模式:客户端下载、广告

  2007年目标:增加用户、同更多运营商签约、加入高级付费服务

  15.www.soonr.com(移动)

  公司总部:坎普贝尔

  员工人数:30人

  创建时间:2005年

  创始人:马丁·弗里德-尼尔森(Martin Frid-Nielsen)

  商业模式:付费用户

  2007年目标:推出高级服务

  16.www.turn.com(广告)

  公司总部:圣马蒂奥

  员工人数:26人

  创建时间:2005年

  创始人:吉姆·巴莱特(Jim Barrett)、约翰·埃里斯(John Ellis)

  商业模式:广告

  2007年目标:同更多发行人签约

  17.www.adify.com(广告)

  公司总部:圣布鲁诺

  员工人数:40人

  创建时间:2005年

  创始人:拉里·布雷曼(Larry Braitman)

  商业模式:广告

  2007年目标:同更多发行人签约

  18.www.admob.com(广告)

  公司总部:圣马蒂奥

  员工人数:22人

  创建时间:2006年

  创始人:奥马尔·哈姆伊(Omar Hamoui)

  商业模式:广告

  2007年目标:开发手机交户广告技术

  19.www.spotrunner.com(广告)

  公司总部:洛杉矶

  员工人数:150人

  创建时间:2004年

  创始人:尼克·格鲁夫(Nick Grouf)、大卫·维克斯曼(David Waxman)

  商业模式:广告

  2007年目标:进军电视、广播等其它媒体

  20.www.vitrue.com(广告)

  公司总部:

亚特兰大

  员工人数:38人

  创建时间:2006年

  创始人:雷吉·布拉福德(Reggie Bradford)

  商业模式:广告

  2007年目标:开发面向特定媒体客户的新网站

  21.www.successfactors.com(企业)

  公司总部:圣马蒂奥

  员工人数:约为400人

  创建时间:2001年

  创始人:拉斯·达尔加德(Lars Dalgaard)

  商业模式:付费用户

  2007年目标:进军亚洲和欧洲市场、开发面向特定行业的网络服务

  22.www.janrain.com(企业)

  公司总部:波特兰

  员工人数:11人

  创建时间:2006年

  创始人:斯科特·凯维顿(Scott Kveton)

  商业模式:广告

  2007年目标:同大网站合作、推出新产品

  23.www.logoworks.com(企业)

  公司总部:林顿

  员工人数:120人

  创建时间:2001年

  创始人:摩根·林奇(Morgan Lynch)

  商业模式:服务费用

  2007年目标:向小公司销售服务

  24.www.reardencommerce.com(企业)

  公司总部:福斯特城

  员工人数:155人

  创建时间:2000年

  创始人:帕特里克·格拉迪(Patrick Grady)

  商业模式:付费用户

  2007年目标:进军移动市场

  25.www.simulscribe.com(企业)

  公司总部:纽约

  员工人数:8人

  创建时间:2003年

  创始人:詹姆斯·西米诺夫(James Siminoff)

  商业模式:付费用户

  2007年目标:同全国性(美国)运营商合作


http://tech.sina.com.cn/i/2007-02-23/08431388241.shtml

什么样的人热爱开源社区

开放源代码领域资深专家PHP之父Rasmus Lerdorf,在互联网精英技术大会上谈到了自己喜欢上开放源代码的过程。他认为,有四类人对开放源代码热情最高。

Rasmus Lerdorf现在是Yahoo!全球的架构师。他在1995年成功开发了PHP项目,被誉为PHP之父,同时他对其他一些开源项目也作出了巨大的贡献。

Rasmus Lerdorf总结认为:

第一类是精英人群。Rasmus 说这些人知道需要通过合作,才能完成更多的工作。他说,"只有我愿意把这个代码给别人,帮助别人解决问题的话,这样别人才可能跟我组成同伴小组。"Rasmus说,很多人在一起工作的时候,会更容易解决一些大家共同面对的问题。

第二类是自我表达欲望特别强的人。"画家总是特别希望别人看到他的画,"Rasmus说程序员也希望别人来承认他们,让他的同伴和同事知道他在做什么,这是一种自我表达的方式。Rasmus说虽然编程的过程很枯燥,但是通过编程最后解决了某个问题,"我会非常高兴"。

第三类是拥有很多激情的人。Rasmus说很多人没有太多的社交活动,但是与别人分享劳动成果会让他觉得非常兴奋。在与很多人互动中,他们会觉得特别有成就感。

第四类是一些很奇怪的人。有些人认为通过他们的贡献,这个世界会变得更好。因此这些人会很热衷于将他们的成果贡献出来。()

文字绣

lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKittyHell
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKittyHelloK
ittyHe
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKittyHelloKit
tyHell
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
ittyHelloKitty
HelloK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
tyHelloKittyHe
lloKit
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
HelloKittyHell
oKitty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
HelloK
ittyHe
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKit
tyHell
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKitty
HelloK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
ittyHe
lloKit
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
tyHell
oKitty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
HelloK
ittyHe
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKit
tyHell
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKitty
HelloK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKittyHe
ll
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKittyHell
oK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
ittyHelloK
it
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
tyHelloKit
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
ty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
He
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
ll
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
ittyHelloK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
it
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
ty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
He
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
ll
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
tyHelloKit
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKitty
He
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
ittyHe
ll
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
ll
oK
ittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oK
it
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKittyHelloKit
ty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKittyHelloKitty
HelloKitty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKittyHelloKittyHe
lloKittyHe
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
HelloKittyHell
oKittyHell
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKittyHelloK
ittyHelloKit
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKit
tyHelloKit
tyHelloKit
tyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKitty
HelloKitty
HelloKitty
HelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHe
lloKittyHe
lloKittyHe
lloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHell
oKittyHell
oKittyHell
oKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloKittyHelloK
ittyHelloK

My photo
London, United Kingdom
twitter.com/zhengxin

Facebook & Twitter