项目10 编写shell脚本(麒麟欧拉版)_第1页
项目10 编写shell脚本(麒麟欧拉版)_第2页
项目10 编写shell脚本(麒麟欧拉版)_第3页
项目10 编写shell脚本(麒麟欧拉版)_第4页
项目10 编写shell脚本(麒麟欧拉版)_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

公司近期有一大批新员工入职,大路安排小乔为新员工创建登录Linux服务器的用户账号和初始密码。虽然小乔已经对添加用户的命令useradd非常熟悉了,但是她觉得使用useradd命令一个一个地添加用户,效率太低而且容易出现错误,有没有什么方法可以提高效率?小乔主动思考如何提升工作效率的态度让导师大路很是欣慰,他告诉小乔可以利用shell编写程序,实现批量添加用‍户。对于小乔来讲,这是一个从未接触过的领域,于是她请教了有经验的同事。同事告诉她,shell也可以像C语言和Java一样定义变量、使用分支和循环等,在实际工作中通常利用shell脚本完成自动化任务,如批量添加、文件备份、定时文件清理‍等。在同事的指点下,小乔的思路越来越明‍确。理解shell脚本的概‍念。学会使用shell脚本创建程‍序。掌握分支结构的用‍法。掌握循环结构的用‍法。具有精益求精的工匠精神。具有担当精神。1创建shell脚本2条件测试与分支结构3循环结构10.1创建shell脚本10.1.1创建并运行shell脚本shell脚本是一种为shell编写的脚本程‍序。1.理解shell脚本shell脚本是一种高效、便捷的编程工具,无需编译即可直接执行,极大地简化了编程流程。此外,它具备数组处理、循环控制、条件分支和逻辑运算等丰富的编程特性,使得自动化任务处理变得高效而灵活。shell脚本的结构如图10-1所示。由此可以看出,shell脚本由以#!开头的解释器、以#开头的注释行和程序体3个部分组‍成。图10-1

shell脚本的结构10.1.1创建并运行shell脚本2.编写shell脚本下面以输出HelloWorld!为例,讲解shell脚本的编写及运行方‍法。(1)编写程序实现输出HelloWorld!。[root@Server~]#mkdirshellscript[root@Server~]#cdshellscript/[root@Servershellscript]#vimHelloWorld.sh1#!/bin/bash2#Program3#Thisprogramshows"HelloWorld!"inyourscreen.4#History5#2020/06/08testFirstrelease6echo-e"HelloWorld!\n"10.1.1创建并运行shell脚本(2)注意事‍项

1

行的#!/bin/bash不能省略,该行表示执行脚本时,使用的shell脚本的解释器为/bin/bash。

第2~第5行为注释行,以#开头,通常用于标注程序的功能、创建时间、修改时间等。在编写程序时,添加适当的注释是良好的编程习惯,有利于以后的维护工‍作。

第6行为主程序部分,使用echo命令输出HelloWorld!。10.1.1创建并运行shell脚本(3)设置执行权限,并运行HelloWorld.sh文‍件。编写完HelloWorld.sh文件后,在目录shellscript下,可以通过shHelloWorld.sh、sourceHelloWorld.sh和./HelloWorld.sh等3种命令运行该脚‍本。[root@Servershellscript]#shHelloWorld.shHelloWorld!或者[root@Servershellscript]#sourceHelloWorld.shHelloWorld!或者[root@Servershellscript]#chmoda+xHelloWorld.sh[root@Servershellscript]#./HelloWorld.shHelloWorld!10.1.2定义shell变量、接收用户输入的数据:read命令在shell脚本中,为了构建更复杂的功能,可以定义多种类型的变量,并且支持与用户互动来动态赋值,从而增强了脚本的交互性和适应‍性。1.shell变量的类型与其他程序设计语言中的变量一样,shell变量也可以根据作用范围分为全局变量和局部变‍量。

全局变量又被称为环境变量,其作用范围包括当前shell进程及其子进‍程。

局部变量的作用范围仅限制在其命令行所在的shell或shell脚本文件‍中。10.1.2定义shell变量、接收用户输入的数据:read命令2.设置shell环境变量shell环境变量一般是指用export命令设置的变量,用于设置shell程序的运行环‍境。环境变量可以在命令行中设置,用户退出shell时,这些变量值会丢失,若想要永久保存环境变量,可在用户主目录下的.bash_profile或.bashrc文件中定义,也可以在/etc/profile文件中定义,这样每次用户登录时,这些变量都将自动设‍置。10.1.2定义shell变量、接收用户输入的数据:read命令(1)在命令行中使用export命令设置环境变‍量。在bash中,设置环境变量可以使用export命令,命令格式如‍下。export环境变量名=变量值使用export命令设置用户的主目录为/home/test,并使用cd$HOME命令切换到用户主目录,如‍下。[root@Server~]#mkdir/home/test[root@Server~]#exportHOME=/home/test[root@Serverroot]#cd$HOME[root@Server~]#pwd/home/test[root@Server~]#echo$HOME/home/test10.1.2定义shell变量、接收用户输入的数据:read命令(2)修改/etc/profile文件,设置环境变‍量。使用export命令可以设置临时性的环境变量,退出shell时,这些环境变量就失效了,若想永久保存环境变量,需要修改/etc/profile文‍件。若要为Java设置环境变量,可在/etc/profile文件的最后加入如下代‍码。[root@Server~]#vim/etc/profileexportJAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.362.b09-2.el9_1.x86_64exportPATH=$PATH:$JAVA_HOME/bin[root@Server~]#source/etc/profile[root@Server~]#echo$JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.362.b09-2.el9_1.x86_6410.1.2定义shell变量、接收用户输入的数据:read命令3.定义shell局部变量shell局部变量一般在shell脚本中定义,只在当前shell脚本执行期间有效。定义局部变量命令格式如‍下。变量名=变量值变量的命名需遵循一定的规则,具体如‍下。

变量名由数字、字母、下画线等组成,必须以字母或者下画线开‍头。

等号两侧不能有空‍格。

变量值若包含空格,则必须用引号引起‍来。

变量名建议大写,便于与shell命令区‍分。10.1.2定义shell变量、接收用户输入的数据:read命令【例10-1】

定义变量VAR、STR,并输出变量的‍值。[root@Server~]#VAR=100[root@Server~]#STR="HelloLinux"[root@Server~]#echo$VAR100[root@Server~]#echo$STRHelloLinux10.1.2定义shell变量、接收用户输入的数据:read命令【例10-2】

定义变量A,值为HelloWorld,并输出变量A。[root@Server~]#vimprinta.sh#!/bin/bash#对变量赋值A="HelloWorld"echo"Ais:"echo$A[root@Server~]#shprinta.shAis:HelloWorld10.1.2定义shell变量、接收用户输入的数据:read命令4.接收用户输入的数据:read命令read命令用于接收从键盘输入的数据,并将其作为变量的值。此命令通常用在shell脚本与用户进行交互的场合中。命令格式如‍下。read[选项]变量名read命令的常用选项如表10-1所‍示。10.1.2定义shell变量、接收用户输入的数据:read命令【例10-3】

通过“请输入你的密码:”提示用户输入密码,用户输入密码之后,在屏幕上输出“密码已输入。”[root@Serverscripts]#vimpassword.sh#!/bin/bash#提示用户输入密码echo"请输入你的密码:"#读取用户输入readpassword#输出提示信息echo"密码已输入。"[root@Serverscripts]#shpassword.sh请输入你的密码:123456密码已输入。10.2条件测试与分支结构10.2.1条件测试test命令用来检查某个条件是否成立。执行条件测试操作以后,通过预定义变量$?获取测试命令的返回值,返回值为0表示条件成立,返回值为1表示条件不成‍立。常见的测试类型有文件测试、整数值比较、字符串比较和逻辑测试‍等。1.文件测试test命令可以对文件进行测试,如test-efilename用于表示判断文件名是否存在。文件测试的常用选项如表10-2所‍示。表10-2文件测试的常用选项10.2.1条件测试【例10-4】

使用test命令判断/root目录是否存‍在。[root@Server~]#test-e/root[root@Server~]#echo$?0echo$?语句用于查看上一条命令的返回值,返回值为0表示/root目录存‍在。10.2.1条件测试2.整数值比较test命令可以将两个整数进行比较,如testnum1-eqnum2表示判断num1和num2是否相等。整数值比较的常用选项如表10-3所‍示。表10-3

整数值比较的常用选项10.2.1条件测试【例10-5】

使用test命令比较10和11是否相‍等。[root@Server~]#test10-eq11[root@Server~]#echo$?1通过echo$?语句查看到上一条命令的返回值为1,表示10和11不相‍等。10.2.1条件测试3.字符串比较test命令可以将两个字符串进行比较,如test-zstring表示判断字符串string是否为空。字符串比较的常用选项如表10-4所‍示。选项说明-z判断字符串是否为空-n判断字符串是否不为空str1=str2判断字符串str1是否等于字符串str2str1!=str2判断字符串str1是否不等于字符串str210.2.1条件测试【例10-6】

使用test命令判断字符串sas和sas是否相‍等。[root@Server~]#test"sas"="sas"[root@Server~]#echo$?0通过echo$?语句查看到上一条命令的返回值为0,表示两个字符串相‍等。10.2.2if语句4.逻辑测试shell提供了与、或、非等逻辑运算来测试某个条件是否成立。逻辑测试的常用选项如表10-5所‍示。表10-5

逻辑测试的常用选项选项说明!表达式测试表达式是否为假表达式1-a表达式2测试两个表达式是否同时为真,也可以用&&表示表达式1-o表达式2测试两个表达式是否至少有一个为真,也可以用||表示【例10-7】

使用test命令判断/root目录是否不存‍在。[root@Server~]#test!-e/root/[root@Server~]#echo$?1通过echo

$?语句查看到上一条命令的返回值为1,表示/root目录存‍在。10.2.2

if语句if语句有3种类型:单分支if语句、双分支if语句、多分支if语‍句。1.单分支if语句单分支if语句是常见的条件判断式。当条件成立时,执行相应的操作,否则不执行任何操作,其语法格式如‍下。if[条件表达式];then

命令序列fi单分支if语句的流程如图所‍示。10.2.2

if语句【例10-8】

编写如下程序,检查某个服务(如firewalld服务)的运行状态,文件名为checkstatus.sh,测试运行结果。[root@Server~]#vimcheckstatus.sh#!/bin/bash#获取服务状态service_status=$(systemctlis-activefirewalld)if["$service_status"="active"]thenecho"firewalld服务正在正常运行。"fi[root@Server~]#chmoda+xcheckstatus.sh[root@Server~]#./checkstatus.shfirewalld服务正在正常运行。在上述案例中首先需要获取firewalld服务的状态,然后判断它是否正常运行,因此可以使用单分支if语句。如果firewalld服务被关闭或者异常终止,就需要用到双分支if语句了10.2.2

if语句2.双分支if语句

双分支if语句在条件成立和条件不成立时执行不同的操作,其语法格式如‍下。if[条件表达式];then

命令序列1else

命令序列2fi双分支if语句的流程如图所‍示。10.2.2

if语句【例10-9】

使用双分支if语句改进例10-8,测试运行结果。[root@Server~]#vimcheckstatus.sh#!/bin/bash#获取服务状态service_status=$(systemctlis-activefirewalld)if["$service_status"="active"]thenecho"firewalld服务正在正常运行。"elseecho"firewalld服务已停止。"fi[root@Server~]#systemctlstopfirewalld.service[root@Server~]#shcheckstatus.shfirewalld服务已停止。10.2.2

if语句3.多分支if语句多分支if语句能针对多个条件执行不同操作,其语法格式如‍下。if[条件表达式1];then

命令序列1elif[条件表达式2];then

命令序列2elif……else

命令序列nfi多分支if语句的流程如图所‍示。10.2.2

if语句【例10-10】

根据firewalld服务的不同状态提示不同内容,并对已停止的服务进行重启操作。[root@Server~]#vimcheckstatus.sh#!/bin/bash#获取服务状态service_status=$(systemctlis-activefirewalld)if["$service_status"="active"]thenecho"firewalld服务正在正常运行。"elif["$service_status"="inactive"]thenecho"firewalld服务已停止,正在尝试重启..."systemctlrestartfirewalldelif["$service_status"="failed"]thenecho"firewalld启动失败。"elseecho"firewalld服务状态异常,请手动检查。"fi[root@Server~]#chmoda+xcheckstatus.sh[root@Server~]#./checkstatus.shfirewalld服务已停止,正在尝试重启...运行脚本:10.2.3case语句在例10-10中,我们利用多分支if语句根据firewalld服务的不同状态输出不同提示内容。可以发现,随着分支增多,代码量增加,且逻辑易混乱。此时,可使用case语句实现多分支的条件判断,使代码简洁清晰。case语句的语法格式如‍下。case变量in

值1)

命令序列1;;

值2)

命令序列2;;

值3)

命令序列3;;……*)

默认命令序列;;esac10.2.3case语句(1)使用case语句需要注意以下3点。①

首行关键字是case,末行关键字是esac(case反过来写)。②

值后面都有)。③

每条分支语句结尾一般会有一对分号即;;。(2)case语句的执行过程如‍下。①shell通过计算变量的值,将其结果依次与值1、值2、值3……比较,直到找到一个匹配‍项。②

找到匹配项,执行它后面的命令,直到遇到一对分号即;;为止。若找不到匹配项,则执行*)默认命令序‍列。10.2.3case语句case语句的流程如图10-5所‍示。10.2.3case语句【例10-11】

使用case语句实现:根据firewalld服务的不同状态提示不同内容,对于已停止的服务进行重启操作。[root@Server

~]#

vim

caselevel.sh#!/bin/bash#

获取服务状态service_status=$(systemctl

is-active

firewalld)#

使用

case

语句根据变量的值执行不同的代码块case

$service_status

in

"active")

echo

"firewalld

服务正在正常运行。"

;;

"inactive")

echo

"firewalld

服务已停止,正在尝试重启…"

systemctl

restart

firewalld

;;

"failed")

echo

"firewalld启动失败。"

;;

*)

echo

"firewalld

服务状态异常,请手动检查。"

;;esac[root@Server

~]#

sh

caselevel.shfirewalld

服务正在正常运行。[root@Server

~]#

systemctl

stop

firewalld.service[root@Server

~]#

sh

caselevel.sh

firewalld

服务已停止,正在尝试重启…运行脚本:10.3循环结构10.3.1for循环语句for循环语句对一个变量依次赋值后,重复执行同一个命令序列。对于赋给变量的几个数值,既可以在程序中以数值列表的形式提供,又可以在程序以外以位置参数的形式提供。for循环语句有如下两种语法格‍式。1.for循环语句的第一种语法格式for循环变量名in取值列表do

命令序列done使用该语法格式需要注意以下3点。

取值列表指的是循环变量所能取到的值的列‍表。do和done之间的所有语句称为循环‍体。

循环执行的次数取决于取值列表中元素的个‍数。该语句的执行流程如图所‍示。10.3.1for循环语句2.for循环语句的第二种语法格式

for

((初始值;

限制值;

执行步长))do

命令序列done

使用该语法格式的for循环语句时,需要注意以下3点。

初始值通常表现为条件变量的初始化语句。

限制值用来决定是否执行for循环。

执行步长通常用来改变条件变量的值,如递增或递减。10.3.1for循环语句【例10-12】

以目的地址为192.168.135.0/24

的网段为例,对一个连续的IP地址范围进行连通测试。[root@Server

~]#

vim

forloop.sh

#!/bin/bash#

定义

IP

地址的前缀,即网络号prefix="192.168.135."#

遍历主机号为

1

254

IP

地址for

i

in

{1..254}do

ip="${prefix}${i}"

echo

"正在对

$ip

进行连通测试..."

#

执行

ping

命令,发送

4

个数据包

ping

-c

4

"$ip"

>

/dev/null

2>&1

if

[

$?

-eq

0

];

then

echo

"$ip

可以连通。"

else

echo

"$ip

无法连通。"

fidone[root@Server

~]#

sh

forloop.sh正在对

192.168.135.1

进行连通测试...192.168.135.1无法连通。……运行脚本:10.3.1while循环语句while循环语句也称为不定循环语句,其语法格式如‍下。while条件测试do

命令序列done当条件测试成立时,执行命令序列,不成立时,跳出循‍环。该语句的执行流程如图所‍示。10.3.1while循环语句【例10-13】

对一个连续的IP地址范围进行连通测试。

[root@Server

~]#

vim

whileloop.sh

#!/bin/bash#

定义

IP

地址的前缀,即网络号prefix="192.168.135."#

初始化计数器i=1#

当计数器小于等于

254

时,执行循环体while

[

$i

-le

254

]do

ip="${prefix}${i}"

echo

"正在对

$ip

进行连通测试..."

#

执行

ping

命令,发送

4

个数据包

ping

-c

4

"$ip"

>

/dev/null

2>&1

if

[

$?

-eq

0

];

then

echo

"$ip

可以连通。"

else

echo

"$ip

无法连通。"

fi

#

计数器加

1

i=$(($i+1))done[root@Server

~]#

sh

whileloop.sh正在对

192.168.135.1

进行连通测试...192.168.135.1

无法连通。……运行脚本:10.3.1until循环语句until循环语句也称为不定循环语句,其执行过程与while循环语句的正好相反,其语法格式如‍下。until条件测试do

命令序列done当条件测试成立时,终止循环,不成立时,执行循环中的命令序‍列。10.3.1until循环语句[root@Server

~]#

sh

untilloop.sh正在对

192.168.135.1

进行连通测试...192.168.135.1

无法连通。……运行脚本:【例10-15】

对一个连续的

IP

地址范围进行连通测试。[root@Server

~]#

vim

untilloop.sh#!/bin/bash#

定义

IP

地址的前缀,即网络号prefix="192.168.135."#

初始化计数器i=1#

当计数器小于等于

254

时,执行循环体until

(($i>254))do

ip="${prefix}${i}"

echo

"正在对

$ip

进行连通测试..."

#

执行

ping

命令,发送

4

个数据包

ping

-c

4

"$ip"

>

/dev/null

2>&1

if

[

$?

-eq

0

];

then

echo

"$ip

可以连通。"

else

echo

"$ip

无法连通。"

fi

#

计数器加

1

i=$(($i+1))done10.3.1until循环语句使用while、until、for循环语句时,如果希望在不满足结束条件的情况下跳出循环,需要使用break或者continue语句。break与continue语句的区别如‍下。break:用于跳出当前循环体,终止循环语句,执行done后面的语‍句。continue:用于跳过当前循环体内剩余未执行的语句,重新判断循环条件,以便执行下一轮循‍环。1创建用户信息文件2编写shell脚本3运行shell脚本项目实施任务10-1创建用户信息文件任务10-1创建用户信息文件为了更好地完成本任务,我们做如下约‍定。(1)新用户的用户名来自一个包含文件名列表的文件userlist,文件内容如表10-6所‍示。(2)用户的密码与用户名相‍同。(3)这些用户都属于新员工用户组newgroup。表10-6

userlist文件内容用户名密码LiLeiKylin123HanMeiMeiKylin123MengLiKylin123HuFeiKylin123LiuMingKylin123WangLeiKylin123任务10-1创建用户信息文件(1)新建空文件userlist。[root@Server~]#touchuserlist(2)把用户名和密码分为两列添加到文件中,保存并退‍出。[root@Server~]#vimuserlistLiLeiKylin123HanMeiMeiKylin123MengLiKylin123HuFeiKylin123LiuMingKylin123WangLeiKylin123任务10-2编写shell脚本任务10-2编写shell脚本(1)新建空文件createuser.sh。[root@Server~]#touchcreateuser.sh(2)使用Vim编辑器编写createuser.sh脚本,输入如下内‍容。[root@Server~]#vimcreateuser.sh#!/bin/bashUsers=/root/userlist#批量新增用户的内容文件UserAdd=/usr/sbin/useradd#新增用户命令路径Passwd=/usr/bin/passwd#设置用户密码命令路径Cut=/bin/cut#字符串分割命令路径whilereadLINES#逐行读取用户数据文件任务10-2编写shell脚本do

USERNAME=$(echo

$LINES

|$Cut

-f1

-d

'

')

#从每行中分割出用户名

PASSWORD=$(echo

$LINES

|$Cut

-f2

-d

'

')

#从每行中分割出用户密码

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论