`
weiyinchao88
  • 浏览: 1184214 次
文章分类
社区版块
存档分类
最新评论

Unix/Linux 平台任务的自动化

 
阅读更多


转载自:水木清华BBS


本章要点:

本章介绍用来替代shell脚本的工具,如TCL和perl。

本章具体包括以下内容。

TCL/expect的使用

awk语言的基本知识

perl语言的基本知识

11.1TCL和expect

TCL是一种类似shell脚本的语言,你可以使用它来完成许多操作。不过,我介绍它的
主要原因是expect是从它发展出来的。如果你想要写一个能够自动处理输入输出的脚本
(如向用户提问并且验证密码)又不想面对C或者Perl,那么expect是你的唯一选择。

11.1.1TCL语言

要使用TCL,你必须先安装这个程序:

%rpm-qtcl

tcl-8.0.5-30

TCL语言可以用交互式或者脚本的方式执行,要使用交互式的TCL环境,只要输入

$tclsh

%

出现的"%"符号是TCL的提示符,然后就可以使用TCL命令的。

如果你要使用脚本方式的TCL,首先把你的脚本写成一个文本文件,例如test.tcl,然
后执行

$tclshtest.tcl

在tcl脚本中,每一行或者是一个命令行,或者是一个注释。注释行必须以#符号开头
,而命令行最好以分号结束,虽然不一定要这样做,但是这样做可以免去不少麻烦。

变量

在tcl中,有两种基本类型的变量,即标量和数组。标量就是一般的数字或者字符串变
量,可以用set语句定义同时赋值:

%seti1

1

字符串应该用引号括起来:

%setstr"test"

'test'

要输出一个标量的内容,使用put语句:

%puts$str

test

$用来说明str是一个变量。puts函数在标准输出显示变量的内容。

数组也可以用set语句定义,实际上,tcl中建立数组只是单个建立数组的元素。例如


%setarr(1)0

0

%setarr(2)1

1

这样就建立了一个两个元素的数组arr。在TCL中,不存在相当于数组边界这样的东西
,例如

%setarr(100)to

to

这时数组中实际只存在arr(1),arr(2)和arr(100),这是和C语言不同的地方。用arr
aysize命令可以返回数组的大小:

%arraysizearr

3

访问数组的方法和访问标两实际是一样的,例如:

%puts$arr(100)

to

可以用同样的方法创建多维数组。

要使用数组中的所有元素,需要使用一种特殊的便利方式。首先要启动startsearsh:

%arraystartsearcharr

s-1-arr

这里返回了一个搜索id,你可以把它传递给某个变量,因为以后还要使用它进行进一
步的搜索:

%setmy_id[arraystartsearcharr]

s-1-arr

现在my_id的内容是s-1-arr,然后,就可以搜索arr的内容了:

%arraynextelementarr$my_id

whi

这里的arraynextelement返回的是什么?可能有点出乎你的意料,是arr数组的下标
,再执行一次arraynextelement命令又会找出另外一个下标:

%arraynextelementarr$my_id

4

这样遍历下去,可以找出arr数组的所有下标,而知道下标之后,就可以用$arr(4)之
类的方式访问arr的内容了。当遍历完成之后,arraynextelement命令将简单地返回:

%arraynextelementarr$my_id

%

这时就可以停止遍历过程了,如果你想确认遍历是否完成,可以使用arrayanymore命
令:

%arrayanymorearr$my_id

0

返回0说明遍历已经完成。

串处理

TCL中可以进行一般的串处理过程,这可以使用string命令和append命令,append命令
将某个字符串加到另外一个字符串的后面:

%setstr1"test"

test

%setstr2"cookit"

cookit

%appendstr1$str2"andother"

testcookitandother

string命令可以执行字符串的比较,删除和查询,其格式是string[参数]string1
[string2]

参数可以是下面的命令之一:

compare按照字典顺序对字符串进行比较,根据相对关系返回-1,0或者+1。

first返回string2中第一次出现string1的位置,如果失败,返回-1。

last返回string2中最后一次出现string1的位置,如果失败,返回-1

trim从string1中删除开头和结尾的出现在string2中的字符

trimleft从string1中删除开头的出现在string2中的字符。

trimright从string1中删除结尾的出现在string2中的字符

下面几个用在string中的参数不需要string2变量:

length返回tring1的长度

tolower返回将string1全部小写化的串

toupper返回将string1全部大写化的串

运算

TCL的运算方式比较别扭,它使用expr命令作为计算符号,其用法类似C语言的+=和/=
,例如,

%setj[expr$i/5]

1

注意TCL会自动选择整数或者浮点计算:

%setl[expr$i/4.0]

1.25

%setl[expr$i/4]

1

在TCL里面可以使用+-*/和%作为基本运算符,另外通常还包括一些数学函数,如a
bs,sin,cos,exp和power(乘方)等等。

另外,还有一个起运算符作用的命令incr,它用来对变量加一:

%seti1

1

%incri

2

流程控制

tcl支持分支和循环。分支语句可以使用if和switch实现。if语句的和C语言类似,如

if{$x<0}{

sety10;

}

注意判断子句也需要使用花括号。

与C语言一样,tcl的if语句也可以使用else和elseif。

switch语句的用法有点类似这样:

switch$x{

0{sety10;}

10{sety100;}

20{sety400;}

}

与C的switch语句不同,每次只有符合分支值的子句才被执行。

循环命令主要由for,foreach和while构成,而且每一个都可以使用break和continue
子句。

for语句的格式有点类似这样:

for{seti0}{$i<10}{incri}{puts$i}

将会输出从1到9的整数。

如果用while循环,这个句子可以写成

while{$i<10}{

puts$i;

incri;

}

foreach是对于集合中的每一个元素执行一次命令,大致的命令格式是

foreach[变量]{集合}{

语句;

}

例如

%foreachj{135}{

put$j;

}

1

3

5

函数

如同在一般的编程语言里面一样,在tcl里面也可以定义函数,这是通过proc命令实现
的:

procmy_proc{i}{

puts$i;

}

这样就定义了一个名字叫proc的函数,它只是在终端显示输入变元的内容。

要使用这个函数,简单地输入它的名字:

%my_proc{5}

5

如果变元的数目是0,只要使用空的变元列表,例如procmy_proc{}{语句;}


尽管tcl还可以处理更复杂的过程,但是我们不再介绍了,例如文件的读写以及tk图形
语言,因为我们处理tcl的主要目标就是理解expect,对于更复杂的编程工作,我们建议
你使用perl。

11.1.2expect

expect是建立在tcl基础上的一个工具,它用来让一些需要交互的任务自动化地完成。
我们首先从一个简单的例子开始,如同在这一节一开始就提到的,我们想设置一个自动
的文件下载程序。

我们看一看这样的一个例子脚本:

#!/usr/bin/expect

spawnftp202.199.248.11

expect"Name"

send"ftp/r"

expect"Password:"

send"nothing/r"

expect"apply"

send"cd/pub/UNIX/Linux/remoteX/r"

expect"successful."

send"bin/r"

expect"settoI"

send"getexceed5.zip/r"

expect"complete."

send"quit/r"

这个是什么意思?呵呵,就是个自动下载程序。第一行说明这个程序应该调用/usr/b
in/expect去执行,然后的就是expect命令。

察看expect的手册页面(manexpect)可以得到一个很长的expect说明,可惜其中关于
expect的语法仍然介绍的不够。一般来说,expect主要用在需要自动执行人机交互的过
程中,例如fsck程序,这个程序会不断地提问"yes/no",像这样的命令就可以用expect
来完成。

spawn语句在expect脚本中用于启动一个新的进程,在我们的程序中,spawnftp202
.199.248.11就是去执行ftp程序,接下来,就是expect和send的指令对了。

每一对expect和send指令代表一个信息/回应。如果这样说不好理解的话,那么可以看
一看ftp的具体执行过程:

ftp202.199.248.11

Connectedto202.199.248.11.

220mail.asnc.edu.cnFTPserver(BeroFTPD1.3.3(3)SunFeb2015:52:49CST
2000.

Name(202.199.248.11:wanghy):

显然,一旦连接成功,服务器会返回一个Name(202.199.248.11:wanghy):的字符串来
要求客户给出用户名。expect语句简单地在返回信息中查询你给出的字符串,一旦成功
就执行下面的命令,现在,expect"Name"已经成功地找到了Name字符串,接下来可以
执行send命令了。

send命令比expect命令更简单,它简单地向标准输入提交你设定的字符串,现在设置
为send"ftp/r"表示等到登录信息之后就给出一个输入ftp回车,也就是标准的登录过
程。

下面的行与这些行完全一样,只是机械地等待服务器的回应,并且提交自己的输入。

要使用这个expect脚本,你只需要将它设置为可执行的属性,然后执行它,expect就
会执行你需要的服务。

由于expect是tcl的扩展,所以你在expect文件中可以象tcl脚本一样设置变量和程序
流程。

现在我们看一看我们还能够如何改进我们的expect脚本。ftp命令可能会失败,比如远
端的机器可能会无法提供服务,或者在启动ftp命令时本地机器发生问题。为了处理这一
类的问题,我们可以使用expect的timeout选项来设置超时的话expect脚本自动退出:

#!/usr/bin/expect

spawnftp202.199.248.11

expect{

timeoutexit

Connect

}

………………

注意这里面使用的花括号。它的含义是使用一组并列表达式。使用并列表达式的主要
原因是这样:如果使用下面的指令对:

expecttimeout

exit

那么由于expect脚本是顺序执行的,那么当程序执行到这个expect的时候就会阻塞,
所以程序会一直等待到timeout然后退出。并列表达式则是相当于switch的行为,只要列
出的几项内容有一项得到满足,expect命令就得到满足,于是程序可以正常执行。上面
的脚本表示,如果连接ftp的时候发生了超时,那么就退出,否则,一旦发现Connect应
答,说明服务器已经正常了,那么就可以继续运行了。

我们可以看看用tcl能够对我们的expect脚本提供什么帮助。我们可以设置让expect脚
本不断地连接远端服务器的服务,直到正常建立连接开始,为此,我们可以把建立连接
的命令放在一个循环里面,并且根据回应的不同自动选择重新输入命令还是继续执行:

spawnftp

while{1}{

expect"ftp>"

send"o202.199.248.11/r"

expect{

"Connected"break

"refused"{sleep10};

}

}

这里使用了我们在tcl语言中讲到的while和break命令,熟悉C的读者应该很容易看出
它的行为:不断地等待ftp>提示符,在提示符下面发送连接远端服务器的命令,如果服
务器回应是refused(连接失败),就等待10秒钟,然后开始下一次循环;如果是Conne
cted,那么就跳出循环执行下面的命令。sleep是expect的一个标准命令,表示暂停若干
秒钟。

expect还支持许多更复杂的进程控制方式,如fork,disconnect等等,你可以从手册
页面中得到详细的信息。另外,各种tcl运算符和流程控制命令,包括tcl函数也可以使
用。

有些读者可能会问,如果expect执行的话是否控制台输入不能使用了,答案是否定的
。expect命令运行时,如果某个等待的信息没有得到,那么程序会阻塞在相应的expect
语句处,这时,你在键盘上输入的东西仍然可以正常地传递到程序中去,其实对于那些
expect处理的信息,原则上你输入的内容仍然有效,只是expect的反映太快,总是抢在
你的前面“输入”就是了。知道了这一点之后,你就可能写一个expect脚本,让expect
自动处理来自fscki的那些恶心的yes/no选项(我们介绍过,这些yes/no其实完全是多余
的,正常情况下你除了选择yes之外什么也干不了)。

缺省下,expect在标准输出(你的终端上)输出所有来自应用程序的回应信息,你可
以用下面的两个命令重定向这些信息:

log_file[文件名]

这个命令让expect在你设置的文件中记录输出信息。必须注意,这个选项并不影响控
制台输出信息,不过如果你通过crond设置expect脚本在半夜运行的话,你就确实可能需
要这个命令来记录各种信息了。例如:

log_fileexpect.log

log_user0/1

这个选项设置是否显示输出信息,设置为1时是缺省值,为0的话,expect将不产生任
何输出信息,或者说简单地过滤掉控制台输出。必须记住,如果你用log_user0关闭了
控制台输出,那么你同时也就关闭了对记录文件的输出。

这一点很让人困扰,如果你确实想要记录expect的输出却不想让它在控制台上制造垃
圾的话,你可以简单地把expect的输出重定向到/dev/null:

./test.exp>/dev/null

你可以象下面这样使用一对fork和disconnect命令。expect的disconnect命令将使得
相应的进程到后台执行,输入和输出被重定向到/dev/null:

if[fork]!=0exit

disconnect

fork命令会产生出一个子进程,而且它产生返回值,如果返回的是0,说明这是一个子
进程,如果不为0,那么是父进程。因此,执行了fork命令之后,父进程死亡而子进程被
disconnect命令放到后台执行。注意disconnect命令只能对子进程使用。

11.2awk和文件的处理

UNIX里面充斥着各种记录文件和类似的东西。对文本文件的处理是系统管理员每天重
要的工作,例如从系统记录中查找重要的内容,或者对某种程序的输出进行统计等等。
我们将介绍常用的一个处理程序,即gawk。

11.2.1grep和正则表达式

让我们首先从grep命令开始。这个命令大家应该很熟悉了,它用来在文件中查找一个
字符串。不过,实际上,grep的处理功能要强大和复杂的多。

grep命令的语法是

grep[模式][文件名]

如果没有给出文件名,就缺省使用标准输入。grep每次读取一行,并且和给出的模式
进行匹配,如果成功就把这一行会显,例如:(粗体的是我们输入的内容)

$greptest

close

testmyhand

testmyhand


grep的“模式”也称为正则表达式,可以由各种基本的正则表达式元素构成。正则表
达式元素主要包括下面几种:

字符串匹配任何字符串,例如greptest表示在标准输入中1

[...]封闭集中匹配一个字符,如:[abcde]可以匹配a,b,c,d,e

[^...]求补集中匹配一个字符,例如[^ABC]匹配

.匹配任意字符

/s空白符

/S非空白符

/d数字

/D非数字

/w字母或数字

/W非字母和数字

*匹配任何字符

上面的形式是grep中使用的基本正则表达式,另外,还可以使用egrep,egrep是grep
的一个扩展版本,支持下面这些扩展的正则字符串:

^匹配一行的开始

$匹配一行的结尾

()确定正则表达式求值顺序,和正常演算中的括号意思差不多。

(...|...|...)或,可选项之一进行匹配,例如:(abc|dev|ghi)可以匹配abc,dev,gh
i,而(ww|gg)do可以匹配wwdo或者ggdo。

+一次或多次模式

如:aba+匹配aba,abaa...不匹配ab

通常,我们有两种方法使用grep和egrep,一种是使用管道,例如我们应该熟悉的ps
ax|grepsendmail,另一种是直接在文件中搜索对应的字符串。

grep/egrep还可以在命令行使用开关,常用的开关包括:

-b在行前加上块号

-c统计匹配行的个数

-n在行前加上行号

-w将模式解释为字符串,所有正则表达式的控制命令失效

-x精确匹配

-r查询文件时包含子目录

举个例子来说,我们想在/var/log/httpd/access_log中查询所有不是来自本地(192
.168.0.1)的请求记录,可以执行:

grep–v"^192.168.0.1"/var/log/httpd/access_log

^用来让grep只在行首匹配。

在grep查询的时候可以使用通配符代表多个文件,例如,grepstart*-r将在当前目
录以及所有子目录的所有文件中查询start字符串。

11.2.2gawk的使用方法

gawk是awk的一个实现,awk是一种用来处理报告等文本文件的脚本语言。不过,我们
介绍这个产品的主要目标是用它来处理各种程序的记账文件。对于复杂的脚本,还是用
Perl比较合适。

gawk的主要功能是针对档案的每一行搜寻指定的模式。,每当找到一个匹配的模式
,gawk就会去执行你设定的动作。按照这个方式,gawk依此方式处理输入档案的每一
行直到输入档案结束。如果对于某个模式没有设置对应的动作,gawk将直接将这个行显
示出来。

为了使用gawk,你通常必须先写一个awk脚本,除非模式/动作非常简单,可以在一行
上完成。我们用一个例子来解释gawk的基本用法,首先产生一个目录列表文件:

ls–l/etc>list

现在list的内容有点像这样:

total2164

drwxr-xr-x3rootroot4096Feb1522:55CORBA

-rw-r--r--1rootroot2045Sep241999DIR_COLORS

-rw-r--r--1rootroot17Mar2519:59HOSTNAME

…………

现在我们选择一个最简单的例子,简单地查找所有属性是drwxr-xr-x的目录文件:

gawk'/drwxr-xr-x/{print$0}'list

将输出所有这样的目录。

这个例子看上去没有什么实际用处,因为用grep也可以做同样的动作,那么我们可以
看一看下面这个功能:

$gawk'$1=="-rwxr-xr-x"{sum=sum+$5}END{printsum}'list

15041

这个是什么意思?对于所有属性是755的文件,让gawk对第五栏的数字求和。第五栏我
们可以看到就是文件的长度,因此这个命令将显示所有属性为755的文件的总共的长度。

$n是gawk中非常重要的概念,它用来表示文本串的分栏。缺省的情况下,gawk将输入
字符串(从文件中读入的每一行)按照分割的空格分成若干个字段,每个字段作为一个
变量,例如有一行

mynameis3thtest

那么,在awk读入这一行之后,就产生了$1到$5变量,其中$1="my",$2="is",………
,最后$5="test"。另外还有一个特殊的变量$0,它表示整个输入行,也就是这个字符串
"mynameistest"。另外还有一个特殊的变量NF,它表示当前行的字段的个数,在现在
的情况下,NF应该等于5。

在某些特殊的情况下,你可能需要改变分割符的定义,这可以通过对FS赋值来完成,
例如FS=","将分割符定义为都号而不是缺省的空格。

在一般情况下,gawk可以从命令文件中获得模式/动作,命令文件的格式很简单,就是
直接将应该写在命令行上的模式/动作对写在文件里面,每个对构成一行,模式可以有两
种,一种是模式匹配,也就是我们在前面解释的正则表达式,如果使用正则表达式,那
么需要用两个/把它们夹在一起,例如/[A-Z]/表示正则表达式[A-Z]。

另一种模式是比较指令,比较指令可以用比较操作符和逻辑运算符来构成,常用的比
较操作符有:

==等于<=不大于~按照正则表达式匹配

<小于>=不小于!~按照正则表达式不匹配

>大于!=不等于

逻辑运算符有

&&和||或!非()括号


设定了模式后,就可以设置对应的动作了,在gawk中,动作必须用花括号括起来。ga
wk能完成的动作并不多,毕竟它是一种报告分析语言。一般情况下,只要熟悉print和p
rintf命令就足够了,print命令的格式非常简单:

printitem1,item2,…………

输出时,每个项目输出一栏,中间用空格分开。一个print后面不跟着任何变量会导致
gawk显示当前的输入行($0)。如果要输出一个字符串,使用引号把它括起来,特别是
如果要输出一个空行,使用print""。这里是一个例子,它将list文件的头两栏输出:

gawk'{print$1,$2}'list

由于输入的文本文件内容有多行,你在命令栏中设计的模式/动作会对每一行执行一次
。就是:

total2164

drwxr-xr-x3

-rw-r--r--1

-rw-r--r--1

-rw-r--r-1

…………………

如果你要精确地控制输出,也可以使用printf命令,这个命令的格式是:

printfformat,item1,item2,...

format参数就是C语言里面的格式控制符,例如%c,%d,%f等等。在%与格式控制
字母之间可加入modifier,modifier是用来进一步控制输出的格式。可能的modifie
r如下所示:

'-'使用在width之前,指明是向左靠齐。如果'-'没有出现,则会在被指定的
宽度向右靠齐。例如:

printf"%-4S","foo"会印出'foo'。

'width'这一个数字指示相对应的栏位印出时的宽度。例如:

printf"%4s","foo"会印出'foo'。

width的值是一个最小宽度而非最大宽度。如果一个item的值需要的宽度
比width大,则不受width的影响。例如printf"%4s","foobar"将印出'foobar'。

'.prec'此数字指定印出时的精确度。它指定小数点右边的位数。如果是要印出一个
字串,它指定此字串最多会被印出多少个字符。

作为一种脚本语言,gawk允许使用变量,定义变量非常简单,就是直接用等号对它赋
值。为了在gawk程序的开始处对变量赋值,gawk专门提供了BEGIN语句,这个语句将在所
有行被读入之前执行,而且只执行一次,通常用它来执行初始化命令,例如

BEGIN{sum=0;count=0;average=0.0;}

对于变量可以使用数学表达式进行运算,运算符包括常见的加减乘除算符,以及^(乘
方),%(取余)和著名的++,--。不过注意gawk在做除法的时候总是使用浮点除法,除了
取余算符%。

函数

另外,gawk包含下列函数:

数学函数

atan2(x,y)y/x的正切

cos(x)余弦函数

sin(x)正弦函数

int(x)取整

log(x)取自然对数

exp(x)指数函数

rand(x)生成一个0到1之间的随机数

srand()初始化随机数发生器

systime()返回从1970年1月1日0:00到当前时间的秒数

sqrt(x)取x的平方根

字符串函数

index(string1,string2)

它会在string1里面,寻找string2第一次出现的地方,返回值是字串string2出
现在字串string1里面的位置。如果找不到,返回值为0。

例如:

printindex("peanut","an")

会印出3。

length(string)

string字符串的长度

例如:

length("abcde")

是5。

match(string,regexp)

match函数会在字串string里面,寻找符合regexp的最长、最靠左边的子字
串。返回值是regexp在string的开始位置,即index值。这个函数会设定内部变量
RSTART等於index,内部变量RLENGTH等於符合的子串个数。如果不符合,则会设定
RSTART为0、RLENGTH为-1。

sprintf(format,expression1,...)

跟C语言的sprintf差不多。

例如:

sprintf("pi=%.2f(approx.)',22/7)

传回的字串为"pi=3.14(approx.)"


sub(regexp,replacement,target)

在字串target里面,寻找符合regexp的最长、最靠左边的地方,并且以字串
replacement代替最左边的regexp。

例如:

str="water,water,everywhere"

sub(/at/,"ith",str)

结果字串str会变成

"wither,water,everywhere"


gsub(regexp,replacement,target)

gsub与前面的sub类似。在字串target里面,寻找符合regexp的所有地方
,以字串replacement代替所有的regexp。

例如:

str="water,water,everywhere"

gsub(/at/,"ith",str)

结果字串str会变成

'wither,wither,everywhere"

substr(string,start,length)

传回字串string的子字串,这个子字串的长度为length个字符,从第start
个位置开始。

例如:

substr("washington",5,3)

传回值为"ing"

如果length没有出现,则传回的子字串是从第start个位置开始至结束。

例如:

substr("washington",5)

传回值为"ington"

tolower(string)

将字串string的大写字母改为小写字母。

例如:

tolower("MiXeDcAsE123")

传回值为"mixedcase123"


toupper(string)

将字串string的小写字母改为大写字母。

例如:

toupper("MiXeDcAsE123")

传回值为"MIXEDCASE123"

其他函数

system(command)

此函式允许使用者执行作业系统的指令,执行完毕後将回到gawk

程式。

例如:

BEGIN{system("ls")}

控制流

在gawk命令脚本中可以使用控制流,主要是if,for,while等语句,用法和C语言相当
类似:


if(condition)then-body[elseelse-body]

如果condition为真(true),则执行then-body,否则执行else-body。

举一个例子如下:

if(x%2==0)

print"xiseven"

else

print"xisodd"


while(condition)

body

while语句测试condition表达式。假如condition为真则执行body的语句。一次
执行完後,会再测试condition,假如condition为真,则body会再度被执行。这个
过程会一直被重复直到condition不再是真。如果condition第一次测试就是伪(fals
e),则body从没有被执行。

下面的例子会印出每个输入行的前三个栏位。

gawk'{i=1

while(i<=3){

print$i

i++

}

}'

do

body

while(condition)

这个doloop执行body一次,然後只要condition是真则会重复执行body。即使
开始时condition是伪,body也会被执行一次。

下面的例子会印出每个输入记录十次。

gawk'{i=1

do{

print$0

i++

}while(i<=10)

}'

for(initialization;condition;increment)

body

此叙述开始时会执行initialization,然後只要condition是真,它

会重复执行body与做increment。

下面的例子会印出每个输入记录的前三个栏位。

gawk'{for(i=1;i<=3;i++)

print$i

}'

break会跳出包含它的for、while、do-while循环的最内层。

下面的例子会找出任何整数的最小除数,它也会判断是否为质数。

gawk'#findsmallestdivisorofnum

{num=$1

for(div=2;div*div<=num;div++)

if(num%div==0)

break

if(num%div==0)

printf"Smallestdivisorof%dis%d/n",num,div

else

printf"%disprime/n",num}'

continue使用于for、while、do-while循环内部,它会跳过循环体的剩余部分
,立刻进行下一次循环的执行。

下面的例子会印出0至20的全部数字,但是5并不会被印出。

gawk'BEGIN{

for(x=0;x<=20;x++){

if(x==5)

continue

printf("%d",x)

}

print""

}'

next语句强迫gawk立刻停止处理目前的行而继续下一个输入行。

exit语句会使得gawk程式停止执行而跳出。然而,如果END出现,它会去执
行END的actions。


自定义函数

你可以定义自己的函数,其格式是

functionname(parameter-list){

body-of-function

}


name是所定义的函数名字。parameter-list是函数的变量列表。变量间使用逗号分
开。

函数可以在程序的任何地方定义,不过习惯上总是定义在程序的开头部分。

下面这个例子,会将每个记录的第一个栏位之值的平方与第二个栏位之值的平方加
起来。

{print"sum=",SquareSum($1,$2)}


functionSquareSum(x,y){

sum=x*x+y*y

returnsum

}

如果你熟悉任何编程语言,那么掌握awk都是很轻松的事情,如果你不喜欢它,那么你
可以参考我们下面介绍的perl。

11.3Perl

Perl是从awk发展起来的,它由LarryWall在1986年发明。它是一种功能强大的编程语
言,而且可以在许多平台上使用。实际上,你完全可以将Perl作为一种标准编程语言(
而不是脚本语言)来使用,笔者非常喜欢它,并且建议所有不想学习C语言的UNIX管理员
应该掌握Perl的基本编程技术。目前,常用的版本是perl5,几乎所有的Linux发行版本
都会包含它,缺省时,linux的perl5安装在/usr/bin下,命令是/usr/bin/perl.


11.3.1基本语法


perl的语法介于C和basic之间,一个perl程序由若干行组成,使用的时候由perl解释
程序解释执行。每个完整的行都应该用分号结尾。

Perl的基本语法是这样的:

①变量和运算符

在perl中,所有变量都不需要提前声明。一旦对某个变量赋值,就自动产生了这个变
量。perl的变量有普通变量,数组和关联数组三种。普通变量就是数值和字符串,要声
明一个普通变量,在变量名字前面加上$,例如

$string1="aaa";

$test=5;

$u=1.33;

同样,访问变量内容也需要使用$符号。


数组用@字符标志,如

@name1=("tom","marry","john");

$b=$name[0];$b现在等于"tom"

$b=@name[0];跟上一句是一样的

$name[0,2]=["help","so"];现在@name等于[“help","marry","so"]

@name[0,2]==@name[2,0];交换0,2元素

数组的大小不是固定的,你可以动态地添加数组元素,例如

$name[3]="app";增加一个元素

直接访问数组名字将得到数组中元素的个数,例如:

$count=@name;将name的元素个数存放到$count变量中。


关联数组是一种特殊的数组,每个元素都由一对元素构成。或者说,关联数组是一种
下标不是整数的数组,要声明一个关联数组,使用%符号,例如:

%arr=(1,"one",2,"two",3,"three",4,"four");

这时可以用前面的值(key)来索引后面的值:

$one=$arr{1};这时$one等于"one"

注意关联数组的访问方式,是使用$关联数组名字[索引号]。

你可以把关联数组看成数据库的一种实现。与一般的数组一样,其大小也可以动态调
节:

$arr{5}="five";增加一对数据。

可以将关联数组简单地变成普通数组,例如

@X=%arr;现在@X的内容是X[0]="1",X[1]="one",……………

perl的运算符与C语言以及我们介绍的gawk很相似,包括普通的+-*/%以及来自C语言的
逻辑运算符&&(和),||(或),等等,下面是一个列表:

+-*/四则运算,注意perl的除法是浮点除法

$a%$ba对b取余数,例如3%2的结果是1

$1..$2区段运算符,这个算符取出$1和$2中间的所有值,例如1..9返回一个表
1,2,………9。通常用这个命令初始化一个数组,例如:@dec=1..9;@oth=(1..26,'A
'..'Z')等等。

=赋值算符

><>=<===!=

这几个算符是数字之间的比较算符。

perl中没有专门的boolean型变量,而是象C语言一样认为所有不为零的量为真值,而
0或者空字符串为假。与C语言类似,Perl支持以下的逻辑运算符:

&&与||或!非

同样,perl也支持位运算:

&与||或^异或

还有就是与C语言相似的运算符使用方式,如

$i+=$j;等效于$i=$i+$j,同样还可以使用$i-=5;$i&=12。这样的算式

$i++;等效于C语言的++,将i加一,++$i,$i--,--$i都是可以使用的。

除了上面的标准算式之外,perl支持字符串运算,首先是字符串之间的比较命令:

$str1gt$str2$str1大于$str2

$str1lt$str2$str1小于$str2

$str1ge$str2$str1不小于$str2

$str1le$str2$str1不大于$str2

$str1eq$str2$str1等于$str2

$str1ne$str2$str1不等于$str2

$str1cmp$str2根据$str1是大于,等于还是小于$str2,返回1,0或者-1。

上面的字符串比较都是使用字典顺序,即ASCII码的顺序。

另一个非常有用的运算符是点号运算符,这个运算符用于把两个字符串连接成一个,
例如:

$str1="string1";

$str2="string2";

$string3=$str1.$str2;这时$string3等于"string1string2"

②基本语句和函数:

#


这个符号代表注释的开始。


print


显示字符串,写文件,如

print"hello/n";或者print"thevaris$i","/n";注意变量名会自动地被替换成变
量值,除非你用一个/符号明确地告诉perl:

print"/$iisastr";

printFILE"hello/n";向FILE对应的文件写,FILE是一个文件句柄;

split分割字符串,格式split(/模式/,$string);

例如$string="i:am:perl";

@list=split(/:/,$string);

#这时@list=("i","am","perl")

($a,$b,$c)=split(/:/,$string);


delete$ARRAY(key)


这个函数用于在关联数组中删除一对记录。例如,%arr=(1,”one”,2,”two”,3,”
three”);delete$arr(2);执行上述操作之后,%arr的内容变为(1,”one”,2,”two
”)。


keys(%ARRAY)


取出关联数组%ARRAY中所有的索引key。这个操作将返回一个数组。例如,对于上面的
%arr,执行@test=key(%arr)的结果是@test成为(1,2)。


values(%ARRAY)


取出关联数组%ARRAY中所有的value,同样返回一个数组,例如对于%arr,@test=val
ues(%arr)的结果是@test变成(”one”,”two”)。


reverse(@array)


把@array反转排列。例如@test=(1,2,5,3,10),@other=reverse(@test)的结果是@ot
her变成(10,3,5,2,1)。


sort(@array)


排序,注意这个排序是按照字符串的排序,例如@other=sort(@other)的结果是(1,
10,2,3,5)。


chop($string)


删除字符串的最后一个字符,通常用于去掉输入字符串中的回车符。


lenth($string)


取字符串长度


substr($string,offset,length)


取字符串子串,即从$string的offset偏移量处截取length长度的字符串作为子串返回


index($string,$substring)


在$string中查找$substring,成功的话,返回$substring在$string中的偏移量,如
果不存在就返回-1。


push(@array,$string)


在@array末尾加入$string


pop(@array)


删除@array的末尾元素并返回这个元素


shift(@array)


删除@array的开头元素并且返回这个元素


join($string,@array)


在@array中间加入$string并返回结果


grep(/pattern/,@array)


在@array中用正则方式查找符合条件的元素


hex($string)


将16进制转化为十进制


rand


产生随机数,注意应该先执行srand初始化随机数种子。


localtime


返回时间数组


dieLIST


显示字符串并且退出程序


pack("格式”,LIST)


把一个LIST转换成指定的二进制格式,例如:$string=pack('C",65)这时$string等于
ASCII的65,即"A"


反引号


用反引号将某个字符串括起来的效果是使perl执行系统命令,这里使用的反引号是大
键盘最左边键,如`ls`执行ls命令。


③使用文件


在perl中使用文本文件非常简单,只要使用open和close打开和关闭文件:


open打开文件

close关闭文件


open函数的格式是open(Filehandle,$filename),这个操作将会打开$filename文件
,并且让Filehandle句柄指向打开的文件。如果失败,将返回false。缺省下,文件是以
只读的方式打开的。如果要打开名字为$filename文件用于输出,使用open(Filehandle
,">$filename")。想要在某个文件的后面追加内容,使用open(Filehandle,">>$filena
me")。当然,open(Filehandle,"<$filename")也是可以使用的,不过这就等于open(Fi
lehandle,"$filename")。

read读文件,格式是read(Filehandle,$string,length),这函数从Filehandle指向
的文件中读取length个字符,存放到$string变量中。如果你要得到标准输入,使用STD
IN的句柄。

close(Filehandle)将关闭由open语句打开的文件。

除了用read语句的标准方法之外,还有一个经常用的方法:

$filecontent=<FILE>;从句柄FILE指向的文件中读取一行,内容存入$filecontent变
量。如果你要从控制台读取一个字符串,使用$input=<STDIN>;就可以了。

下面是一个例子:

$filename="test";

open(FILE,"$filename")||die"cannotopenfile!;

while($line=<FILE>{

print"$line";

}

close(FILE);

这个程序实际就是cat命令的perl语言实现,open命令打开当前目录下面的test文件,
并且把句柄返回到FILE变量,注意这一行的用法,Perl的||(或)运算是短路求值的,如
果open成功,那么返回一个非0的数,因此这算式无论如何都会为真,所以会跳过||后面
的东西;否则,如果open失败,perl就要对后面的东西执行一下,于是退出这个程序。

打开成功之后,perl会得到这个文件的句柄,下面的句子就是反复读取文件的每一行
并且显示出来,当文件读到末尾的时候,$line=<FILE>将产生一个空字符串,于是whil
e循环结束。

与shell脚本语言类似,perl还有一些文件测试运算符


-t$file


如果$file这个文件可读,返回1,$file是文件名。


-w$file


如果$file可写,返回1


-x$file


如果$file可以执行,返回1


-e$file


如果$file存在,返回1


-o$file


如果用户是$file的拥有者,返回1


-s$file


返回$file文件的大小


-f$file


是否为正常文件


-T$file


是否文本


-B$file


是否二进制文件


-M$file


文件从更新到现在的日期数


④流程控制


perl支持与C语言很相似的流程控制语句:


if和if..else:

if语句的语法是

if(...){

clause;

}

与C语言不同,即使只有一行程序,if后面的花括号也不能省略,这一点也适用于后面
说的其他复合语句。

与C语言类似,也可以用else和elseif子句:

if(...){

clause1;}

else{

clause2;

}

或者

if(…){

...

}

elseif(…){

....

}

else{

...

}

另外,perl还支持unless语句:

unless(exp1){

clause1;

}

如果exp1不成立,就执行clause1子句。这个unless语句里面也可以使用else子句。实
际上,这就是一种否定形式的if……else语句。


while循环语句:

while的语法有两种,分别是将表达式放在循环首部和尾部,第一种形式是:

while(exp){

clause;

}

第二种形式是

do{

clause;

}

while(exp);

都是循环执行clause直到exp不成立,不过一个在循环头部判断exp表达式是否为真,
另一个是在循环尾部。


until循环


语法是until(exp){

clause;

}

反复执行clause直到exp成立。

for循环


for(初始化;继续条件;增量){


循环体;

}


这个for循环和C的一样,首先执行初始化语句,然后开始循环执行循环体,每次循环
都调用一次增量表达式,直到循环继续条件不再成立。例如

for($1=0;$i<10;$i++){

print$i;

}

将显示出从0到9的所有整数。


foreach$variable(@array){


循环体;

}


这个类似于shell语言的foreach,它把@array的内容一条一条赋给$variable并执行里
面的语句。


跳出循环

有两个语句用来实现特殊控制:


lastif用在循环里,相当于break;

nextif相当于continue.


⑤文字处理运算


除了正常的字符串处理语句外,perl还支持一种文字处理运算方式,基本格式是$str
ing=~(文字处理模式)。这个文字处理模式是perl的主要优点之一,由于perl的文字处
理运算模式太强大了,这里只能介绍几个非常基本的形式。

首先解释一下pattern的概念.pattern一般是用两个/字符夹在一起的一些字符串,用
来代表一些具有某些特点的字符串,实际上,这个patternj基本上就是grep/egrep里面
的正则表达式,只是功能更丰富一点。常用的有:

任意字符串:匹配该字符串

[0-9]匹配所有数字字符

[a-z]所有小写字母

[^0-9]所有的非数字

[^a-z]所有的非小写字母

[A-Z]所有的大写字母

^字符串开头的字符

$字符串结尾的字符

/d跟[0-9]一样

/D非数字字符

/w就相当于[a-zA-Z0-9]

/W相当于[^a-zA-Z0-9]

/s一个空白的字符

/S非空白的字符

/d+一个相当于数字的字符串

/w+一个完全由数字或字符构成的字符串

/b一个不由英文字母或者数字为边界的字符串

/B一个由字母或数字为边界的字符串

a|b|c符合a,b,c之一的字符串

/pattern/ii代表忽略大小写

[]找寻符合[]内的字符,例如[abde]可以匹配a,b,d,e的任何一种

?{m}正好是m个指定的字母

{m,n}多于m少于n个指定的字符

/如果要引用一些在pattern中具有特殊意义的字符,使用/前缀


在perl的文本运算模式中,最常用的是=~或者!~运算符号和s,tr两个函数。=~表示匹配
,它用右边的模式来匹配左边的字符串,如果成功就得到一个true,!~正好相反,代表
不匹配,例如

$string="chmod711cgi";

if($string=~"/chmod/"){

print"Foundchmod!/n";}

$string=~"/chmod/"这样的表达式询问是否/chmod/可以匹配$string,因为$string中
包含chmod,所以if语句会成功地执行。

tr是串转换函数,例如:

$string=~tr/a-z/A-Z/;

将字符串中的小写字母转换成大写.

s是串取代函数,例如:

$string=~s/a/A/;

把第一个a换成A,还可以加后缀g表示全程替换,例如:

$string=~s/1/A/g;

变换后,$string变成chmod7AAcgi.

注意tr和s的区别,tr的多替换一般是一对一的,或者说是字符的替换,而s是字符串的
替换,长度可以改变,例如如果$string的值是chmod711cgi,那么

$string=~s/1/ONE/g;

将变成chmod7ONEONEcgi.而

$string=~tr/1/ONE/;

将把$string变成chmod7oocgi。

还有一个很实用的功能是变数替换,例如:

$string="test24";

$string=~s/(/d+)/<$1>/;

这时,s首先搜索满足/d+(数字)的串,得到24,然后送入$1,接着再套上<>,结果是"tes
t<24>".

⑥内置变量

除了用户定义的变量之外,perl还定义了一些内置变量,它们在perl中有特殊的意义
,用户不能修改它们的含义(有些可以赋值),下面是常用的内置变量:

@ARGV

这是个数组,它代表的是传递给perl程序的命令行开关,如@ARGV[0]是第一个参数,
@ARGV[1]是第二个等等。如果你的perl程序名字叫test,而你用testmeother去调用它
,那么@ARGV[0]是”me”,@ARGV[1]是other,以此类推。

$_和$1,$2,………

这几个参数用于文本处理模式中的临时变量。举个例子来说,串匹配模式中:

$string="chmod711cgi"

$string=~/(/w+)/s+(/d+)/;

看上去这第二行代码什么也不做,因为它仅仅是个匹配语句。不过,实际上,由于pe
rl会把临时变量放进$n变量,所以它会修改$_和$1,………变量。在这个匹配模式中,
首先的/w+匹配一组字符,成功,得到chmod字符串,于是perl将它保存到$1;然后,/s
+匹配一组空白符号,失败;最后,/d+匹配一组数字,成功,得到711,perl将它保存到
$2。

如果在匹配模式中没有指明对那个串变量使用匹配模式,就使用$_进行匹配。

⑦自定义函数

Perl程序中允许定义自己的子程序。例如,下面的语句定义了一个子过程:

submy_proc{

print“thisismysubrouting/n”;

}

sub是子过程的说明,my_proc是过程名字,要调用这个过程,只要使用&符号,例如:

if($want==1){

&my_proc;

}




11.3.2perl的使用

上面介绍了perl的基本语法。要使用perl,你当然可以在交互模式下使用,但是,一
般情况下,我们用perl是代替shell脚本完成自动化任务的。为此,我们需要把perl写成
程序来运行。写perl程序可以用任何文本编辑工具创建,一般总是设置其扩展名为.pl,
虽然实际上扩展名是不需要的。

要运行一个perl程序,有两种方法,一种是调用perl解释器读入perl源程序,例如,
我们已经写了一个perl程序,命名为test.pl,那么,可以用下面的命令执行它:

$/usr/bin/perltest.pl

不过,在一般情况下,我们更喜欢在命令行下面直接敲入程序的名字执行它,为此,
可以在perl程序的头部加入这样的行:

#!/usr/bin/perl

注意#!符号,它告诉shell应该用什么程序来解释当前脚本,这里的定义是/usr/bin/
perl,这是缺省的的perl安装位置。如果你的perl可执行程序放在别的目录下,自己修
改这一行。这样,当shell读到这个文件的时候,就会自动启动perl来解释这个程序。

perl最常用的功能是用来写cgi程序,不过,我们不想涉及cgi程序的细节。相反,我
们介绍如何用perl进行日常管理,用perl程序代替书写晦涩的shell脚本。

让我们从一个我自己的例子开始,我经常要把一些txt文本直接转化成html文本,以便
做进一步的编辑和主页发布,其实这个操作非常简单,就是将回车和大于号,小于号都
换成对应的HTML标记,这可以用word或者netscape来完成,但是如果涉及的文件数目比
较多或者文件比较大,用这些软件就很困难了,所以我写了一个十分简单的perl脚本:

#!/usr/bin/perl

if((@ARGV[0]eq"")||(@ARGV[1]eq"")){

print"convertinputfileoutputfile/n";

exit;}

open(FILE1,"@ARGV[0]")||die"cannotopensourcefile!/n";

open(FILE2,">@ARGV[1]")||die"cannotopentagetfile!/n";


while($line=<FILE1>){


$line=~s/</&lt/g;

$line=~s/>/&gt/g;

$line=~s//^M//g;

$line=~s//n/<BR>/g;

printFILE2$line;


}

close(FILE1);

close(FILE2);

这个程序简单得几乎象是DOS的批命令,首先检查参数是否定义,然后从输入文件中读
取行,把回车和两个尖括号换成对应的html标记,写入对应文件,任务就完成了。要使
用它,比如把test.txt转换成test.html,可以直接执行:

./convert.pltest.txttest.html

perl也可以完成更复杂的操作,最常见的功能扩展是进行网络编程,如直接使用电子
邮件,电子新闻服务等等。不过我们这里不能进一步介绍它的强大功能。对perl感兴趣
的朋友,可以进一步查阅有关书籍学习编程技术。

11.4其他工具

还有很多自动化脚本工具,例如python等等。另外,对于一个职业的系统管理人员,
熟悉C语言的编程是很有好处的。

就我个人而言,我感到,如果你不想学习shell,那么了解expect和perl就足以对付一
般的系统管理工作。另外,还有一些威力强大的可编程工具,一个是我们刚才提到的py
thon,这是一种面向对象的脚本平台,如果你的大部分任务使用shell和expect,那么这
个东西可能很适合你使用。

另外一个非常有争议的产品是emacs。这个编辑工具是GNU计划的头号产物,随着发展
,它已经从原来一个文本编辑程序发展成为一个使用lisp宏控制,几乎可以做文本界面
下的一切事情的集成环境。反对它的理由主要是它的运行速度在低配置的机器上几乎无
法忍受,而且配置起来也十分困难。不论如何,使用emacs有时显得比较有专业特色,至
少是很有GNU的特色
分享到:
评论

相关推荐

    linux/shell大作业

    你可以使用UNIX/LINUX中一些比较简单的命令或命令组合来执行1、2、3、4、5的任务。对于任务6和7,你需要编写单独的Shell脚本文件(必须分别命名为add和delete)并且在你的主脚本menu文件中调用这些脚本文件。

    LINUX/UNIX Shell编程大作业

     你可以使用UNIX/LINUX中一些比较简单的命令或命令组合来执行1、2、3、4、5的任务。对于任务6和7,你需要编写单独的Shell脚本文件(必须分别命名为add和delete)并且在你的主脚本menu文件中调用这些脚本文件。  ...

    WinSCP (Windows Secure Copy) 免费开源的广泛用于与Unix和Linux服务器系统的文件交互

    WinSCP (Windows Secure Copy) 是一个免费、开源的Windows应用程序,主要用于通过...脚本和自动化:WinSCP支持脚本和自动化功能,允许用户自动执行文件传输和同步任务。这对于需要定期执行文件备份或更新的任务非常有

    NetSarang Xmanager Enterprise 6 Build 0175 中文多语免费版.zip

    它能把远端 Unix/Linux 的桌面无缝地带到你的Windows上,甚至当你的电脑是在内网或防火墙后,你也能通过 SSH 协议安全的运行远端的X应用程序。 NetSarang Xmanager Enterprise 特点包括: -可通过 Xcongfig 工具...

    xmanager7 远程工具

    脚本支持 - 支持用户通过脚本自动化日常任务,提高工作效率。 图形用户界面 - 提供直观的图形界面,使得用户可以轻松配置和管理各种选项。 安全性 - 提供高级的加密和认证选项,确保远程连接的安全性。 兼容性 - ...

    Java 调用 Linux shell 命令执行框架:sshxcute

    资源包含sshxcute-1.0.jar及中文使用指南; sshxcute框架简介: 软件开发与测试人员常常会在远程 Linux/UNIX 系统上执行...sshxcute 不管是针对软件开发、测试还是系统部署,都简化了自动化流程与系统环境部署的步骤。

    Linux操作系统下各项服务的解释

     9、crond:cron是Unix下的一个传统程序,该程序周期地运行用户调度的任务。比起传统的Unix版本,Vixie版本添加了不少属性,而且更安全,配置更简单。  10、dhcpd:该精灵提供了对动态主机控制协议(Dynamic Host ...

    Ruby-PuppetLinuxUnix和Windows系统的自动化管理引擎

    Puppet - Linux、Unix和Windows系统的自动化管理引擎,执行管理任务(例如添加用户,安装包和更新服务器配置)基于一个集中的规范。

    Puppet 自动化运维最佳实践

    puppet是一种Linux、Unix、windows平台的集中配置管理系统,使用自有的puppet描述语言,可管理配置文件、用户、cron任务、软件包、系统服务等。puppet把这些系统实体称之为资源,puppet的设计目标是简化对这些资源的...

    Linux环境数据库管理员指南

    9.22 运行时的环境—从 UNIX/Linux 中使用 Postgres 270 9.22.1 启动 postmaster 270 9.22.2 使用 pg_options 270 9.22.3 认可的选项 271 9.23 安全 273 9.23.1 用户验证 273 9.23.2 基于主机的访问控制 273 9.23.3...

    Shell脚本专家指南中文PDF - Linux编程

    主要内容包括如何使小到中型的系统管理任务自动化,分析系统数据并编辑配置文件,使用bash和ksh等编写Linux、Unix和OS X应用程序的脚本文件等。 本书面向中高级的shell程序员,以及需要解决日常问题的系统管理员,但...

    linux快速入门教程(非扫描版)

    • 第五部分—编写Shell 脚本介绍了shell 编程,一个无可否认的基本技能,能够自动化许 多常见的计算任务,很容易学。通过学习shell 编程,你会逐渐熟悉一些关于编程语言方 面的概念,这些概念也适用于其他的编程...

    RED HAT LINUX 6大全

    第1章 Red Hat Linux和UNIX简介 1 1.1 Linux的优点 2 1.2 版权和保证 3 1.3 在哪里可以获取Red Hat Linux 3 1.4 系统需求 3 1.5 小结 4 第2章 Red Hat系统的安装 5 2.1 准备,认真准备 5 2.2 安装Red Hat Linux 6 ...

    睿备份(IBAK)V3.4.1

    1、跨系统、跨平台支持,Windows/Linux/Unix一机(软件)拿下; 2、混合实例技术,不论本地/远程,一机(软件)即可管理所支持的所有数据库软件; 3、自动(计划任务模式)/手工备份本地或远程MSSQL、ORACLE、...

    LINUX 20招

    快速关闭Linux系统 最新版本的Linux/UNIX系统借鉴了大型机的技术,采用了抗掉电的日志式文件系统,可以自动跟踪保存用户数据,自动同步刷新文件系统,用户完全可以随手关闭电源,从而达到快速关闭系统的目的。...

    入门学习Linux常用必会60个命令实例详解doc/txt

    不过目前大多数较新的Linux发行版本(包括红旗 Linux、中软Linux、Mandrake Linux等)都可以自动挂装文件系统,但Red Hat Linux除外。 umount 1.作用 umount命令的作用是卸载一个文件系统,它的使用权限是超级...

    LINUX系统管理白皮书

    对于面向所有主流Linux子系统的支持与管理任务,本书都进行了恰到好处的讲解。涵盖的主题包括文件系统、目录、引导和关机、打印、网络兼容性、网络应用、网络登录、安全、用户账号、数据备份等等。此外,还针对TCP/...

    睿备份 v4.2.5.zip

    1、跨系统、跨平台支持,Windows/Linux/Unix一机(软件)拿下; 2、创新的集中式管理技术,只需在一台计算机安装,即可管理无限台计算机的数据库/文件备份; 3、混合实例技术,可无限扩展任意实例与任务,不在需要...

Global site tag (gtag.js) - Google Analytics