在 Linux 系统中,由于是多人多任务的环境,所以会有多人共同使用一个硬盘空间的情况发生,为了合理使用这些空间,管理员需要控制用户对磁盘空间的使用,这个就是Linux 下的配额管理。
配额管理是对某个磁盘分区进行限制。这里的限制包括2个方面:
1.单个用户对某个目录下空间大小的限制。
2.单个用户对某个目录下文件个数的限制。
1)针对 WWW server ,例如:每个人的网页空间的容量限制。
2)针对 mail server,例如:每个人的邮件空间限制。
3)针对 file server,例如:每个人最大的可用网络硬盘空间。
(1)仅针对整个 partition:
quota针对『整个 partition』进行限制, 例如:如果/dev/hda5 是挂载在 /dave 目录下,那么在 /dave 目录下的所有目录都会受到限制。
(2)只对一般身份使用者有效:
不是所有在 Linux 上面的账号都可以设定 quota,例如 root 就不能设定quota 。
(1)soft limit:
这是最低限制容量的意思,用户在宽限期间之内,他的容量可以超过 soft ,但必需要宽限时间之内将磁盘容量降低到 soft 的容量限制之下。
(2)hard limit:
这是『绝对不能超过』的容量。通常hard limit 会比 soft limit 为高,例如网络驱动器空间为 30 MB ,那么 hard limit 就设定为 30MB ,但是为了让使用者有一定的警戒心,所以当使用空间超过 25 MB 时,例如使用者使用了 27 MB 的空间时,那么系统就会警告用户, 让使用者可以在『宽限时间内』将他的档案量降低至 25 MB ( 亦即是 soft limit )之内。也就是说, soft 到 hard 之间的容量其实就是宽限的容量,可以达到针对使用者的『警示』作用。
(3)宽限时间:
宽限时间就是当使用者使用的空间超过了 soft limit ,却还没有到达 hard limit 时,那么在这个『宽限时间』之内,就必需要请用户将使用的磁盘容量降低到 soft limit 之下。而当用户将磁盘容量使用情况超过 soft limit 时,『宽限时间』就会自动被启动,而在用户将容量降低到 softlimit 之下,那么宽限时间就会自动的取消。
Quota也需要安装,安装包如下:
[root@rhce /]# rpm -q quota
quota-3.17-16.el6.x86_64
[root@rhce /]#
与Quota 相关的几个命令如下。
[root@rhce /]# quotaon
Bad number of arguments.
quotaon: Usage:
quotaon [-guvp] [-F quotaformat] [-x state] -a
quotaon [-guvp] [-F quotaformat] [-x state] filesys ...
-a, --all turn quotas on for all filesystems
-f, --off turn quotas off
-u, --user operate on user quotas
-g, --group operate on group quotas
-p, --print-state print whether quotas are on or off
-x, --xfs-command=cmd perform XFS quota command
-F, --format=formatname operate on specific quota format
-v, --verbose print more messages
-h, --help display this help text and exit
-V, --version display version information andexit
[root@rhce /]#
[root@rhce /]# quotaoff
Bad number of arguments.
quotaoff: Usage:
quotaoff [-guvp] [-F quotaformat] [-x state] -a
quotaoff [-guvp] [-F quotaformat] [-x state] filesys ...
-a, --all turn quotas off for allfilesystems
-f, --off turn quotas off
-u, --user operate on user quotas
-g, --group operate on group quotas
-p, --print-state print whether quotas are on or off
-x, --xfs-command=cmd perform XFS quota command
-F, --format=formatname operate on specific quota format
-v, --verbose print more messages
-h, --help display this help text and exit
-V, --version display version information andexit
[root@rhce /]# warnquota -h
warnquota: Usage:
warnquota [-ugsid] [-F quotaformat] [-c configfile] [-q quotatabfile][-a adminsfile]
-u, --user warn users
-g, --group warn groups
-s, --human-readable send information in more humanfriendly units
-i, --no-autofs avoid autofs mountpoints
-d, --no-details do not send quota informationitself
-F, --format=formatname use quotafiles of specific format
-c, --config=config-file non-default config file
-q, --quota-tab=quotatab-file non-default quotatab
-a, --admins-file=admins-file non-default admins file
-h, --help display this help messageand exit
-v, --version display version informationand exit
Bugs to [email protected]
[root@rhce /]#
[root@rhce /]# edquota
edquota: Usage:
edquota [-rm] [-u] [-F formatname] [-p username] [-f filesystem]username ...
edquota [-rm] -g [-F formatname] [-pgroupname] [-f filesystem] groupname ...
edquota [-rm] [-u|g] [-F formatname] [-f filesystem] -t
edquota [-rm] [-u|g] [-F formatname] [-f filesystem] -Tusername|groupname ...
-u, --user edit user data
-g, --group edit group data
-r, --remote edit remote quota (via RPC)
-m, --no-mixed-pathnames trim leading slashes from NFSv4mountpoints
-F, --format=formatname edit quotas of a specific format
-p, --prototype=name copy data from a prototype user/group
--always-resolve alwaystry to resolve name, even if it is
composed only ofdigits
-f, --filesystem=filesystem edit data only on a specific filesystem
-t, --edit-period edit grace period
-T, --edit-times edit grace time of a user/group
-h, --help display this help text andexit
-V, --version display version informationand exit
Bugs to: [email protected]
[root@rhce /]#
[root@rhce /]# repquota -h
repquota: Utility for reporting quotas.
Usage:
repquota [-vugsi] [-c|C] [-t|n] [-Fquotaformat] (-a | mntpoint)
-v, --verbose display also users/groups withoutany usage
-u, --user display information aboutusers
-g, --group display information aboutgroups
-s, --human-readable show numbers in human friendly units(MB, GB, ...)
-t, --truncate-names truncate names to 8 characters
-p, --raw-grace print grace time in seconds sinceepoch
-n, --no-names do not translate uid/gid to name
-i, --no-autofs avoid autofs mountpoints
-c, --batch-translation translate big number of ids at once
-C, --no-batch-translation translate ids one by one
-F, --format=formatname report information for specific format
-h, --help display this help message andexit
-V, --version display version information andexit
Bugs to [email protected]
[root@rhce /]#
#quotacheck –cvug/tmp
[root@rhce ~]# quotacheck -h
Utility for checking and repairing quotafiles.
quotacheck [-gucbfinvdmMR] [-F
-u, --user check user files
-g, --group check group files
-c, --create-files create new quota files
-b, --backup create backups of old quota files
-f, --force force check even if quotas areenabled
-i, --interactive interactive mode
-n, --use-first-dquot use the first copy of duplicated structure
-v, --verbose print more information
-d, --debug print even more messages
-m, --no-remount do not remount filesystem read-only
-M, --try-remount try remounting filesystem read-only,
continue even if itfails
-R, --exclude-root exclude root when checking allfilesystems
-F, --format=formatname check quota files of specific format
-a, --all check all filesystems
-h, --help display this message and exit
-V, --version display version information andexit
Bugs to [email protected]
[root@rhce ~]#
[root@rhce ~]# quotacheck -cvug /dave
quotacheck: Your kernel probably supportsjournaled quota but you are not using it. Consider switching to journaled quotato avoid running quotacheck after an unclean shutdown.
quotacheck: Scanning /dev/sdc1 [/dave] done
quotacheck: Cannot stat old user quotafile: No such file or directory
quotacheck: Cannot stat old group quotafile: No such file or directory
quotacheck: Cannot stat old user quotafile: No such file or directory
quotacheck: Cannot stat old group quota file:No such file or directory
quotacheck: Checked 3 directories and 2files
quotacheck: Old file not found.
[root@rhce ~]# setquota -h
setquota: Usage:
setquota [-u|-g] [-rm] [-F quotaformat]
setquota [-u|-g] [-rm] [-F quotaformat] <-p protouser|protogroup>
setquota [-u|-g] [-rm] [-F quotaformat] -b [-c] -a|
setquota [-u|-g] [-F quotaformat] -t
setquota [-u|-g] [-F quotaformat]
-u, --user set limits for user
-g, --group set limits for group
-a, --all set limits for allfilesystems
--always-resolve always tryto resolve name, even if is
composed only ofdigits
-F, --format=formatname operate on specific quota format
-p, --prototype=protoname copy limits from user/group
-b, --batch read limits from standard input
-c, --continue-batch continue in input processing in case ofan error
-r, --remote set remote quota (via RPC)
-m, --no-mixed-pathnames trim leading slashes from NFSv4mountpoints
-t, --edit-period edit grace period
-T, --edit-times edit grace times for user/group
-h, --help display this help text andexit
-V, --version display version information andexit
Bugs to: [email protected]
[root@rhce ~]#
[root@rhce /]# fdisk /dev/sdc
Device contains neither a valid DOSpartition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with diskidentifier 0x1e051117.
Changes will remain in memory only, untilyou decide to write them.
After that, of course, the previous contentwon't be recoverable.
Warning: invalid flag 0x0000 of partitiontable 4 will be corrected by w(rite)
WARNING: DOS-compatible mode is deprecated.It's strongly recommended to
switch off the mode (command 'c') and change display units to
sectors (command 'u').
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-652, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G}(1-652, default 652):
Using default value 652
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
[root@rhce /]# fdisk -l
Disk /dev/sdc: 5368 MB, 5368709120 bytes
255 heads, 63 sectors/track, 652 cylinders
Units = cylinders of 16065 * 512 = 8225280bytes
Sector size (logical/physical): 512 bytes /512 bytes
I/O size (minimum/optimal): 512 bytes / 512bytes
Disk identifier: 0x1e051117
Device Boot Start End BlocksId System
/dev/sdc1 1 6525237158+ 83 Linux
[root@rhce /]# mkfs -t ext3 /dev/sdc1
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
327680 inodes, 1309289 blocks
65464 blocks (5.00%) reserved for the superuser
First data block=0
Maximum filesystem blocks=1342177280
40 block groups
32768 blocks per group, 32768 fragments pergroup
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystemaccounting information: done
This filesystem will be automaticallychecked every 30 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
[root@rhce /]#
[root@rhce /]# mount/dev/sdc1 /dave
[root@rhce /]# vim /etc/fstab
/dev/sdc1 /dave ext3 defaults 0 0
我们这里将/dev/sdc1 映射到了目录/dave.
[root@rhce /]# groupadd grp01
[root@rhce /]# groupadd grp02
[root@rhce /]# cat /etc/group|grep grp0*
grp01:x:503:
grp02:x:504:
[root@rhce /]#
[root@rhce /]# useradd dave01 -g grp01
[root@rhce /]# useradd dave02 -g grp02
[root@rhce /]# passwd dave01
Changing password for user dave01.
New password:
BAD PASSWORD: it is too short
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updatedsuccessfully.
[root@rhce /]# passwd dave02
Changing password for user dave02.
New password:
BAD PASSWORD: it is too short
BAD PASSWORD: is too simple
Retype new password:
passwd: all authentication tokens updatedsuccessfully.
[root@rhce /]#
[root@rhce ~]# cat /etc/fstab
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
/dev/sdc1 /dave ext3 defaults,usrquota,grpquot 0 0
[root@rhce ~]#
/etc/fstab 文件的第四个字段是装载文件系统是使用的选项:
(1)实现基于用户的磁盘配额,就加入usrquota关键字,
(2)实现基于组的磁盘配额,就加入grpqouta关键字,如果两者都需要,就全写入,中间可以用逗号分隔。
注意:请特别注意这里的拼写,是usrquota和grpquota,不要写成userquota和groupquota。
[root@rhce ~]# mount
/dev/sda3 on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs(rw,rootcontext="system_u:object_r:tmpfs_t:s0")
/dev/sda1 on /boot type ext4 (rw)
none on /proc/sys/fs/binfmt_misc typebinfmt_misc (rw)
none on /sys/kernel/config type configfs(rw)
sunrpc on /var/lib/nfs/rpc_pipefs typerpc_pipefs (rw)
gvfs-fuse-daemon on /root/.gvfs typefuse.gvfs-fuse-daemon (rw,nosuid,nodev)
/dev/sdc1 on /dave typeext3 (rw)
分区是我们之前mount的,我们后来修改了mount的选项,增加了用户和组的配额,所以这里我们重新mount一次,使我们的修改生效。
[root@rhce ~]# mount -oremount /dave
[root@rhce ~]# mount
/dev/sda3 on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts(rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs(rw,rootcontext="system_u:object_r:tmpfs_t:s0")
/dev/sda1 on /boot type ext4 (rw)
none on /proc/sys/fs/binfmt_misc typebinfmt_misc (rw)
none on /sys/kernel/config type configfs(rw)
sunrpc on /var/lib/nfs/rpc_pipefs typerpc_pipefs (rw)
gvfs-fuse-daemon on /root/.gvfs typefuse.gvfs-fuse-daemon (rw,nosuid,nodev)
/dev/sdc1 on /dave typeext3 (rw,usrquota,grpquota)
[root@rhce ~]#
--检查配额文件
[root@rhce ~]# quotacheck/dave
quotacheck: Cannot create new quotafile/dave/aquota.user.new: Permission denied
quotacheck: Cannot initialize IO on newquotafile: Permission denied
这里关闭SELinux即可:
[root@rhce ~]# getenforce
Enforcing
[root@rhce ~]# setenforce 0
[root@rhce ~]# getenforce
Permissive
[root@rhce ~]#
--启动配额限制
[root@rhce ~]# quotaon -vug /dave
/dev/sdc1 [/dave]: group quotas turned on
/dev/sdc1 [/dave]: user quotas turned on
[root@rhce ~]#
--开启之后,会在/dave的目录下自动创建配额的管理文件:aquota.group和aquota.user
[root@rhce dave]# pwd
/dave
[root@rhce dave]# ll
total 32
-rw-------. 1 root root 6144 Jun 22 09:28 aquota.group
-rw-------. 1 root root 6144 Jun 22 09:28 aquota.user
drwx------. 2 root root 16384 Jun 22 05:00lost+found
[root@rhce dave]#
这个文件我们不能直接编辑,我们需要使用edquota命令来进行编辑。
[root@rhce dave]# edquota -u dave01
Disk quotas for user dave01 (uid 503):
Filesystemblocks soft hard inodessoft hard
/dev/sdc10 10240 20480 0 00
这里的限制分三种:
1.blocks:按block的数量
2.soft:软限制,单位为字节。
3.hard: 硬限制,单位为字节。
上例中,soft限制约为10MB,hard限制约为20MB,当用户dave01使用空间超过10MB时,系统会进行提示,但可以继续使用空间,而当用户dave01使用空间达到20MB时,就会限制用户dave01继续使用/dave空间。
--查看报告:
[root@rhce dave]# repquota /dave
*** Report for user quotas on device/dev/sdc1
Block grace time: 7days;Inode grace time: 7days
Block limits File limits
User used softhard grace usedsoft hard grace
----------------------------------------------------------------------
root-- 141436 00 4 00
--这里只有root用户的信息,因为其他用户还没有创建文件,一旦创建文件,就会限制了。
[root@rhce dave]#
--用dave01用户创建文件进行配额限制的测试
--创建5M的文件:成功
[dave01@rhce ~]$ dd if=/dev/zeroof=/dave/tf01 bs=1M count=5
5+0 records in
5+0 records out
5242880 bytes (5.2 MB) copied, 0.0445553 s,118 MB/s
--创建10M的文件,超过soft 的配额限制,有警告:
[dave01@rhce ~]$ dd if=/dev/zeroof=/dave/tf01 bs=1M count=10
sdc1: warning, user blockquota exceeded.
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.0232663 s,451 MB/s
--在创建10M的文件,超过20M的配额限制,文件创建失败:
[dave01@rhce ~]$ dd if=/dev/zeroof=/dave/tf02 bs=1M count=10
sdc1: write failed, userblock limit reached.
dd: writing `/dave/tf02':Disk quota exceeded
10+0 records in
9+0 records out
10448896 bytes (10 MB) copied, 0.049051 s,213 MB/s
[dave01@rhce ~]$
--查看报告:
[root@rhce dave]# repquota /dave
*** Report for user quotas on device/dev/sdc1
Block grace time: 7days;Inode grace time: 7days
Block limits File limits
User used softhard grace usedsoft hard grace
----------------------------------------------------------------------
root-- 141432 00 3 00
dave01 +-20480 10240 204806days 3 00
这里就显示了dave01这个用户的相关限制。我们这里的宽限时间变成了6days。
配额的限制,除了在磁盘大小上的限制,还可以在文件个数上进行限制。我们这里用dave02这个进行示例。
[root@rhce dave]# edquota -u dave02
Disk quotas for user dave02 (uid 504):
Filesystemblocks soft hardinodes soft hard
/dev/sdc10 0 00 2030
soft和hard同上是软限制和硬限制,分别是20、30,当用户dave02创建文件超过20个时,系统会进行提示,但仍可以继续创建文件,而当用户dave02创建文件超过30个文件时,就会限制用户dave02继续创建文件。
注意:因为用户dave02是在/dave目录下进行了磁盘配额限制,所以/dave目录会算做一个文件,所以dave02最多只能创建29个文件。
[root@rhce ~]# chown dave02.grp02 /dave
--用脚本手动创建文件:
[dave02@rhce ~]$ cd /dave
[dave02@rhce dave]$ ls
aquota.group aquota.userlost+found tf01 tf02
[dave02@rhce dave]$
[dave02@rhce dave]$ for i in $(seq 1 22);
> do echo “dave02file$i”;
> touch dave02file$i;
> done
“dave02file1”
“dave02file2”
“dave02file3”
“dave02file4”
“dave02file5”
“dave02file6”
“dave02file7”
“dave02file8”
“dave02file9”
“dave02file10”
“dave02file11”
“dave02file12”
“dave02file13”
“dave02file14”
“dave02file15”
“dave02file16”
“dave02file17”
“dave02file18”
“dave02file19”
“dave02file20”
sdc1: warning, user filequota exceeded.
“dave02file21”
“dave02file22”
[dave02@rhce dave]$
到20就提示配额限制了。
--继续用脚本创建文件:
[dave02@rhce dave]$ for i in $(seq 23 33);
> do echo “dave02file$i”;
> touch dave02file$i;
> done
“dave02file23”
“dave02file24”
“dave02file25”
“dave02file26”
“dave02file27”
“dave02file28”
“dave02file29”
“dave02file30”
sdc1: write failed, userfile limit reached.
touch: cannot touch`dave02file30': Disk quota exceeded
“dave02file31”
touch: cannot touch `dave02file31': Diskquota exceeded
“dave02file32”
touch: cannot touch `dave02file32': Diskquota exceeded
“dave02file33”
touch: cannot touch `dave02file33': Diskquota exceeded
[dave02@rhce dave]$
这里我们最多只能创建29个文件。
--限制报告:
[root@rhce ~]# repquota /dave
*** Report for user quotas on device/dev/sdc1
Block grace time: 7days;Inode grace time: 7days
Block limits File limits
User used softhard grace usedsoft hard grace
----------------------------------------------------------------------
root-- 141432 00 3 00
dave01+- 20476 1024020480 6days 20 0
dave02-+ 4 00 30 20 306days
通过repquota命令,可以看到block和inode的宽限时间默认都是7天。
[root@rhce ~]# repquota /dave
*** Report for user quotas on device/dev/sdc1
Block grace time: 7days;Inode grace time: 7days
这个时间,我们可以使用edquota 来修改。
[root@rhce ~]# edquota -h
edquota: Usage:
edquota [-rm] [-u] [-F formatname] [-p username] [-f filesystem]username ...
edquota [-rm] -g [-F formatname] [-p groupname] [-f filesystem]groupname ...
edquota [-rm] [-u|g] [-F formatname] [-f filesystem] -t
edquota [-rm] [-u|g] [-F formatname] [-f filesystem] -Tusername|groupname ...
-u, --user edit user data
-g, --group edit group data
-r, --remote edit remote quota (via RPC)
-m, --no-mixed-pathnames trim leading slashes from NFSv4mountpoints
-F, --format=formatname edit quotas of a specific format
-p, --prototype=name copy data from a prototype user/group
--always-resolve alwaystry to resolve name, even if it is
composed only of digits
-f, --filesystem=filesystem edit data only on a specific filesystem
-t, --edit-period edit grace period
-T, --edit-times edit grace time of a user/group
-h, --help display this help text andexit
-V, --version display version informationand exit
--修改用户dave01的宽限时间:
[root@rhce ~]# edquota-T dave01
Times to enforce softlimit for user dave01(uid 503):
Time units may be: days, hours, minutes, orseconds
Filesystemblock grace inodegrace
/dev/sdc1 601938seconds unset
~
这是默认值:
[root@rhce ~]# edquota -T dave01
Times to enforce softlimit for user dave01(uid 503):
Time units may be: days,hours, minutes, or seconds
Filesystemblock grace inodegrace
/dev/sdc110days unset
我们改成10天。 上面有时间的单位。
--查看报告显示:
[root@rhce ~]# repquota /dave
*** Report for user quotas on device/dev/sdc1
Block grace time: 7days; Inode grace time:7days
Block limits File limits
User used softhard grace usedsoft hard grace
----------------------------------------------------------------------
root-- 141432 00 3 00
dave01+- 20476 1024020480 10days 20 0
dave02-+ 4 00 30 2030 6days
[root@rhce ~]# edquota -T dave02
Times to enforce softlimit for user dave02(uid 504):
Time units may be: days, hours, minutes, orseconds
Filesystemblock grace inodegrace
/dev/sdc1unset 12days
~
[root@rhce ~]# repquota/dave
*** Report for user quotas on device/dev/sdc1
Block grace time: 7days; Inode grace time:7days
Block limits File limits
User used softhard grace usedsoft hard grace
----------------------------------------------------------------------
root-- 141432 00 3 00
dave01+- 20476 1024020480 9days 20 0
dave02-+ 4 00 30 2030 12days
我们的dave02 用户对应的组是grp02.
-Tg 争对组
T 争对用户
--默认值:
[root@rhce ~]# edquota -Tg grp02
Times to enforce softlimit for group grp02(gid 504):
Time units may be: days,hours, minutes, or seconds
Filesystemblock grace inodegrace
/dev/sdc1unset unset
--修改:
[root@rhce ~]# edquota -Tg grp02
Times to enforce softlimit for group grp02(gid 504):
Time units may be: days, hours, minutes, orseconds
Filesystemblock grace inodegrace
/dev/sdc1unset 10days
~
但是这里我们一旦保存之后,我们的修改就又还原了。
如果我们想修改组的宽限时间,就必须先设置组的soft和hard limit。 只有这2个属性设置以后,才可以设置宽限时间。
[root@rhce dave]# edquota-g grp02
Disk quotas for group grp02 (gid 504):
Filesystem blocks soft hardinodes soft hard
/dev/sdc14 0 0 30 20 30
这是完以后,就可以设置组的宽限时间了。
[root@rhce dave]# quotaoff -a
--关闭quota之后,在清空/etc/fstab 文件中有关配额的限制。
最后remount 磁盘。
---------------------------------------------------------------------------------------
版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!
Skype: tianlesoftware
Email: [email protected]
Blog: http://blog.csdn.net/tianlesoftware
Weibo: http://weibo.com/tianlesoftware
Twitter: http://twitter.com/tianlesoftware
Facebook: http://www.facebook.com/tianlesoftware
Linkedin: http://cn.linkedin.com/in/tianlesoftware