当前位置:资讯中心主页 >源码天堂 >文章内容
- linux shell script 系统学习
- 来源: ChinaUnix博客 作者: ChinaUnix博客 发布时间:2006-01-01 17:10:00
-
- 域名惊喜价格 cn域名1元注册
- com域名39.9元
域名注册
- 主机按月支付,低至19元/月
- 超大流量,可开子站点
虚拟主机
- 特惠VPS168元/月,4-8M独享带宽保证
- 独立操作系统,无限开站点
VPS主机
在DOS 中,你可能会从事一些例行的重覆性工作,此时你会将这些重覆性的命令写成批次档,只要执行这个批次档就等於执行这些命令。大家会问在UNIX中是否有批次处理这个东东,答案是有的。在UNIX中不只有如DOS 的批次处理,他的功能比起DOS 更强大,相对地也较复杂,已和一般的高阶语言不相上下。在UNIX中大家都不叫做批次档,而叫做Shell Script。
一般而言,Shell Script的地位和其他的可执行档(或命令)是完全相同的,只不过Shell Script是以文字档的方式储存,而非二进位档。而执行Shell Script时,必须有一个程式将其内容转成一道道的命令执行,而这个程式其实就是Shell ,这也就是为什麽我们叫做Shell Script的原因(往後我们称为Script)。不同Shell 的Script基本上会有一些差异,所以我们不能将写给A shell 的Script用B shell 执行。而在UNIX中大家最常使用Bourne Shell及C Shell ,所以这堂课就介绍这两种Script的写法。
将文字档设为可执行的Shell Script
如果我们已写好Script,怎么将其设成可执行档呢?因为Script其实是个可执行档,所以必须将其存取权设定成可执行。我们能使用下列命令更改存取权:
chmod u+x filename 只有自己能执行,其他人不能执行
chmod ug+x filename 只有自己及同一群能执行,其他人不能执行
chmod +x filename 所有人都能执行
而我们怎么指定使用那一个Shell 来解释所写的Script呢?几种基本的指定方式如下所述:
1. 如果Script的第一个非空白字元不是"#",则他会使用Bourne Shell。
2. 如果Script的第一个非空白字元是"#"时,但不以"#!"开头时,则他会使用C Shell。
3. 如果Script以"#!"开头,则"#!"後面所写的就是所使用的Shell,而且要将整个路径名称指出来。
这里建议使用第三种方式指定Shell ,以确保所执行的就是所要的。Bourne Shell的路径名称为/bin/sh ,而C Shell 则为/bin/csh。
1. 使用Bourne Shell
┌??????????┐ ┌??????????┐
│echo enter filename │ │#!/bin/sh │
│ . │ or │ . │
│ . │ │ . │
│ . │ │ . │
└??????????┘ └??????????┘
2. 使用C Shell
┌??????????┐ ┌??????????┐
│# C Shell Script │ │#!/bin/csh │
│ . │ │ . │
│ . │ │ . │
│ . │ │ . │
└??????????┘ └??????????┘
3. 使用/etc/perl
┌??????????┐
│#! /etc/perl │
│ . │
│ . │
│ . │
└??????????┘
除了在Script内指定所使用的Shell 外,你也能在命令列中强制指定。比如你要用C Shell 执行某个Script,你能下这个命令:
csh filename
此时的Script的存取权就不一定要为可执行档,其内部所指定的Shell 也会无效,周详的情形後面会讨论。
□Script的基本结构及观念
Script是以行为单位,我们所写的Script会被分解成一行一行来执行。而每一行能是命令、注解、或是流程控制指令等。如果某一行尚未完成,能在行末加上"\" ,这个时候下一行的内容就会接到这一行的後面,成为同一行,如下
┌???????????┐
│echo The message is \ │
│too long so we have \ │
│to split it into \ │
│several lines │
└???????????┘
当Script中出现"#" 时,再他後面的同一行文字即为注解,Shell 不会对其翻译。
在Script中要执行一个命令的方法和在命令列中相同,你能前景或背景执行,执行命令时也会需要设定一些环境变数。
Script的流程控制和一般高阶语言的流程控制没有什麽两样,也和高阶语言相同有副程式。这些使得Script的功能更加强大。
为了达到和高阶语言相同的效果,我们也能在Script中设定变数,如此使Script 成为一个名付其实的高阶语言。
□Bourne Shell
一、变数
Bourne Shell的变数型态只有字串变数,所以要使用数值运算则必须靠外部命令达 成目的。而其变数种类有下列几种:
1. 使用者变数
这是最常使用的变数,我们能所有不包含空白字元的字串来当做变数名称。 设定变数值时则用下列方式:
var=string
取用变数时则在变数名称前加上一"$" 号。
┌???????┐
│name=Tom │
│echo name │
│echo $name │
└???????┘
结果如下:
name
Tom
2. 系统变数(环境变数)
和使用者变数相似,只不过此种变数会将其值传给其所执行的命令。要将一使 用者变数设定为系统变数,只要加上:
export var
┌???????┐
│name=Tom │
│export name │
└???????┘
以下是使用者一进入系统之後就已设定好的系统变数:
$HOME 使用者自己的目录
$PATH 执行命令时所搜寻的目录
$TZ 时区
$MAILCHECK 每隔多少秒检查是否有新的信件
$PS1 在命令列时的提示号
$PS2 当命令尚未打完时,Shell 需求再输入时的提示号
$MANPATH man 指令的搜寻路径
3. 唯读的使用者变数
和使用者变数相似,只不过这些变数不能被改动。要将使用者变数设成唯读的 ,只要加上:
readonly var
而若只打readonly则会列出所有唯读的变数。更有一点,系统变数不能设定 成唯读的。
┌???????┐
│name=Tom │
│readonly name │
│echo $name │
│name=John │
│readonly │
└???????┘
结果如下:
Tom
name: is read only
readonly name
readonly ......
4. 特别变数
有些变数是一开始执行Script时就会设定,并且不以加以修改,但我们不叫他 唯读的系统变数,而叫他特别变数(有些书会叫他唯读的系统变数),因为这 些变数是一执行程式时就有了,况且使用者无法将一般的系统变数设定成唯读 的。以下是一些等殊变数:
$0 这个程式的执行名字
$n 这个程式的第n个参数值,n=1..9
$* 这个程式的所有参数
$# 这个程式的参数个数
$$ 这个程式的PID
$! 执行上一个背景指令的PID
$? 执行上一个指令的返回值
当你执行这个程式时的参数数目超过9 个时,我们能使用shift 命令将参数 往前移一格,如此即可使用第10个以後的参数。除此之外,吾人能用set 命 令改动$n及$*,方法如下:
set string
如此$*的值即为string,而分解後则会放入$n。如果set 命令後面没有参数, 则会列出所有已设定的变数及其值。
档名:ex1 参数:this is a test
┌???????????┐
│echo Filename: $0 │
│echo Arguments: $* │
│echo No. of args.: $# │
│echo 2nd arg.: $2 │
│shift │
│echo No. of args.: $# │
│echo 2nd arg.: $2 │
│set hello, everyone │
│echo Arguments: $* │
│echo 2nd arg.: $2 │
└???????????┘
结果如下:
Filename: ex1
Arguments: this is a test
No. of args.: 4
2nd arg.: is
No. of args.: 3
2nd arg.: a
Arguments: hello, everyone
2nd arg.: everyone
值得一提的是,当你想从键盘输入一变数值时,你能使用下面的命令:
read var1 var2.....
这时read会将一个字分给一个变数。如果输入的字比变数还多,最後一个变数会将剩下的字当成其值。如果输入的字比变数还少,则後面的变数会设成空字串。 如果需要处理数值运算,我们能使用expr命令。其参数及输出列於附录A。
二、执行命令
在Bourne Shell中有五种方法执行一个命令,而这五种方式所产生的果有些许的不 同。
1. 直接下命令
这个方式和在命令列中直接下命令的效果相同。
2. 使用sh命令
sh command
这个档案必须是Bourne Shell的Script,但这个档案并不一定要设成可执行。 除此之外和直接下命令的方式相同。
3. 使用"."命令
. command
这时和使用sh命令相似,只不过他不像sh一般会产生新的process ,相反地, 他会在原有的process 下完成工作。
4. 使用exec命令
exec command
此时这个Script将会被所执行的命令所取代。当这个命令执行完毕之後,这个 Script也会随之结束。
5. 使用命令替换
这是个相当有用的方法。如果想要使某个命令的输出成为另一个命令的参数 时,就一定要使用这个方法。我们将命令列於两个"`" 号之间,而Shell 会以 这个命令执行後的输出结果代替这个命令及两个"`" 符号。
str=’Current directory is ’`pwd`
echo $str
结果如下:
Current directory is /users/cc/mgtsai
这个意思是pwd 这个命令输出"/users/cc/mgtsai",而後整个字串代替原 来的`pwd` 设定str 变数,所以str 变数的内容则会有pwd 命令的输出。
number=`expr $number + 1`
这就是先前所提要作数值运算的方法,基本上expr命令只将运算式解,而 後输出到标准输出上。如果要将某变数设定成其值,非得靠命令替换的方 式不可。这个例子是将number变数的值加1 後再存回number变数。
三、流程控制
在介绍流程控制之前,我们先来看看test命令。test命令的参数是条件判断式,当 条件为真时则传回非零值,而条件为伪时则传回零。在所有的流程控制都必须用到 test命令来判断真伪。而test命令的使用方法则列於附录B。
test $# = 0
如果执行这个程式没有参数时,会传回非零值代表"$# = 0"这个条件成立。反 之则会传回零。
以下介绍各种流程控制:
1. if then语法及流程图如下
│ FALSE
if (condition) <condition>?┐
then │TRUE │
then-commands then-commands │
fi ├????┘
│
condition 是个test命令。往後所介绍的各种流程中的condition 都是test 命令。
档名:chkarg
┌???????????┐
│if (test $# != 0) │
│ then │
│ echo Arg1: $1 │
│fi │
└???????????┘
$ chkarg Hello
Arg1: Hello
$ chkarg
$
2. if then else语法及流程图如下
│ FALSE
if (condition) <condition>?????┐
then │TRUE │
then-commands then-commands else-commands
else ├????????┘
else-commands │
fi
3. if then elif语法及流程图如下
│ FALSE
if (condition1) <condition1>?┐
then │TRUE │ FALSE
commands1 commands1 <condition2>?┐
elif (condition2) │ │ TRUE │
then │ commands2 commands3
commands2 ├?????┴????┘
else │
commands3
commands3
fi
echo ’word 1: \c’
read word1
echo ’word 2: \c’
read word2
echo ’word 3: \c’
read word3
if (test "$word1" = "$word2" -a "$word2" = "$word3")
then
echo ’Match: words 1, 2, & 3’
elif (test "$word1" = "$word2")
then
echo ’Match: words 1 & 2’
elif (test "$word1" = "$word3")
then
echo ’Match: words 1 & 3’
elif (test "$word2" = "$word3")
then
echo ’Match: words 2 & 3’
else
echo ’No match’
fi
4. for in语法及流程图如下
│ FALSE
for var in arg-list ┌?<arg-list更有东西吗?>?┐
do │ │TRUE │
commands │ 从arg-list取得一项 │
done │ 放到变数var │
│ │ │
│ commands │
└??????┘ │
┌???????????┐ ┌?????┘
│for a in xx yy zz │ │
│ do │
│ echo $a │
│done │
└???????????┘
结果如下:
xx
yy
yy
zz
5. for语法及流程图如下
│ FALSE
for var ┌?<参数中更有东西吗?>?┐
do │ │TRUE │
commands │ 从参数中取得一项 │
done │ 放到变数var │
│ │ │
│ commands │
└?????┘ │
档名:lstarg ┌?????┘
┌???????????┐ │
│for a │
│ do │
│ echo $a │
│done │
└???????????┘
$lstarg xx yy zz
xx
yy
yy
zz
6. while 语法及流程图如下
│ FALSE
while (condition) ┌?<condition>?┐
do │ │TRUE │
commands │ commands │
done └????┘ │
┌????┘
│
┌???????????????┐
│number=0 │
│while (test $number -lt 10) │
│ do │
│ echo "$number\c" │
│ number=`expr $number + 1` │
│done │
│echo │
└???????????????┘
结果如下:
0123456789
7. until语法及流程图如下
│ TRUE
until (condition) ┌?<condition>?┐
do │ │FALSE │
commands │ commands │
done └????┘ │
┌????┘
│
他和while 的不同只在於while 是在条件为真时执行回圈,而until 是在条件 为假时执行回圈。
8. break及continue
这两者是用於for, while, until 等回圈控制下。break 会跳至done後方执行 ,而continue会跳至done执行,继续执行回圈。
9. case语法及流程图如下
│ TRUE
case str in <str=pat1>????commands1?┐
pat1= commands1;; │FALSE TRUE │
pat2= commands2;; <str=pat2>????commands2?┤
pat3= commands3;; │FALSE TRUE │
esac <str=pat3>????commands3?┤
│FALSE │
├????????????┘
│
而pat 除了能指定一些确定的字串,也能指定字串的集合,如下
* 任意字串
? 任意字元
[abc] a, b, 或c三字元其中之一
[a-n] 从a到n的任一字元
| 多重选择
┌???????????????┐
│echo ’Enter A, B, or C: \c’ │
│read letter │
│case $letter in │
│ A|a= echo ’You entered A.’;;│
│ B|b= echo ’You entered B.’;;│
│ C|c= echo ’You entered C.’;;│
│ *= echo ’Not A, B, or C’;; │
│esac │
└????????
Linux程式设计-11.Shell Script(bash)--(1)简介
众所皆知地,UNIX上以小工具着名,利用许多简单的小工具,来完成原本需要大量软体研发的工作,这一点特色,使得UNIX成为许多人心目中最佳的系统平台。
在众多的小工具中,Shell Script算得上是最基本、最强大、运用最广泛的一个。他运用围之广,不仅从系统启动、程式编译、定期作业、上网连线,甚至安装整个Linux系统,都能用他来完成。
因为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",我加上一些实际日常的应用例来说明。希望这样能让那些始终不得其门而入的人们,多多少少能有点概念。
Linux程式设计-11.Shell Script(bash)--(2)教学例
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。
echo是个bash的内建指令。
--------------------------------------------------------------------------------
接下来,执行hello这个script:
要执行一个Script的方式有非常多种。
--------------------------------------------------------------------------------
第一种 : 将hello这个档案的权限设定为可执行。
[foxman@foxman bash]# chmod 755 hello
执行
[foxman@foxman bash]# ./hello
hello world
--------------------------------------------------------------------------------
第二种 : 使用bash内建指令"source"或"."。
[foxman@foxman bash]# source hello
hello world
或
[foxman@foxman bash]# . hello
hello world
--------------------------------------------------------------------------------
第三种 : 直接使用sh/bash/tcsh指令来执行。
[foxman@foxman bash]# sh hello
hello world
或
[foxman@foxman bash]# bash hello
hello world
--------------------------------------------------------------------------------
Bash执行选项
--------------------------------------------------------------------------------
-c string : 读取string来当命令。
-i : 互动介面。
-s : 由stdin读取命令。
- : 取消往後选项的读取。
-norc : 不要读~/.bashrc来执行。
-noprofile : 不要读/etc/profile、~/.bash_profile、~/.bash_login、~/.profile等等来执行。
-rcfile filename : 执行filename,而非~/.bashrc
-version : 显示版本。
-quiet : 启动时不要哩唆。
-login : 确保bash是个login shell。
-nobraceexpansion : 不要用curly brace expansion({}符号展开)。
-nolineediting : 不用readline来读取命令列。
-posix : 改采Posix 1003.2标准。
Linux程式设计-11.Shell Script(bash)--(3)用於自动备份的Shell Script
一个用於自动备份的Shell Script
我们先前提到,可利用Shell Script搭配crond来作定期的工作。要作定期性的工作,在UNIX上,就是和crond的搭配运用。
--------------------------------------------------------------------------------
首先我们先来研究怎么对系统进行备份。
要对系统进行备份,不外乎便是利用一些压缩工具。在许多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.gz
--------------------------------------------------------------------------------
在解过Linux下档案备份的基本知识後,我们来写一个将档案备份的Script。
#!/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
来看看里面的档案列表。
要解开时,可用以下指令来完成复原:
gzip -dc /tmp/backup.tgz | tar -xv
或
tar xvfz /tmp/backup.tgz
备份通常是仅备份系统通常最重要的部份,/etc可说是不可缺少的一部份。另外,看你系统中有那些重要的资料需要备份。通常来说,你没有必要备份/bin、/sbin、/usr/bin、/usr/sbin、/usr/X11R6/bin等等这些执行档目录。只要备份你重要的档案即可,别把整个硬碟备份,那是蛮呆的动作。
--------------------------------------------------------------------------------
如果你有许多台机器,可利用其中一台任务较轻的内部网路主机,做为主要备份主机。将所有机器都自动执行备份,然後利用NFS/Coda/Samba等网路档案系统,将备份的资料放到该备份机器中,该机器则定时收取备份资料,然後你再由该机器中进行一次备份。
这里是整个系统备份方案的图示。
在你进行之前,先解一下,系统中那些是要备份的,那些是不必的。
--------------------------------------------------------------------------------
新的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移到一个只有该备份主机可存取的目录中。
--------------------------------------------------------------------------------
当这些个别的Script都测试好以後,接下来我们将他们放到crontab里面。找到你的crontab,他的位置可能在/var/spool/cron/crontabs/root、/etc/crontab、/var/cron/tabs/root。
在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",在此不详述。
备份主机的设定类同。
注意: 所有机器不要同时进行备份,否则网路会大塞车。备份主机收取备份的时间要设为最後,否则会收不到备份资料。你能在实作後,将时间间隔调整一下。
--------------------------------------------------------------------------------
看看,两个小小不到三行的Shell Script,配合cron这个定时工具。能让原本需要耗时多个小时的人工备份工作,简化到不到十分钟。善用你的想像力,多加一点变化,可你让你的生活变得轻松异常,快乐悠哉。
Linux程式设计-11.Shell Script(bash)--(4)档案系统检查
系统安全一向是大多数计算机用户关心的事,在UNIX系统中,最重视的事,即系统中有没有"木马"(Trojan horse)。不管Trojan horse怎么放进来的,有一点始终会不变,即被放置木马的档案,其档案日期一定会被改动,甚至会有其他的状态改动。此外,许多状况下,系统会多出一些不知名的档案。因此,平日检查整个档案系统的状态是否有被改动,将所有状态有改动的档案,及目前有那些程式正在执行,自动报告给系统管理员,是个避免坐上"木马"的良方。
--------------------------------------------------------------------------------
#!/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 然後把他放到一个不显眼的地方去,让别人未找到。
把他加入crontab中。
30 7 * * * /full_check_script_path/whatever_you_name_it 1> /dev/null 2> /dev/null #上班前检查
有些档案是固定会更动的,像/var/log/messages、/var/log/syslog、/dev/ttyX等等,不要太大惊小怪。
以上内容由 华夏名网 搜集整理,如转载请注明原文出处,并保留这一部分内容。
“华夏名网” http://www.sudu.cn 和 http://www.bigwww.com 是成都飞数科技有限公司的网络服务品牌,专业经营虚拟主机,域名注册,VPS,服务器租用业务。公司创建于2002年,经过6年的高速发展,“华夏名网”已经成为我国一家知名的互联网服务提供商,被国外权威机构webhosting.info评价为25大IDC服务商之一。 - (阅读次数:235)
- 上一篇: The Introduction to GCC翻译组一周工作总结 下一篇: linux shell script 系统学习1
- [
收藏] [
推荐] [
评论] [打印本页] [返回上一页][关闭窗口]




