7.1 实验介绍
7.1.1 实验介绍
在对系统进行运维时,shell 脚本给了我们很大帮助。通过 shell 脚本,可以大大减少工作量。
本实验主要介绍 shell 脚本的概念及使用。
7.1.2 实验目标
掌握全局变量及局部变量;
掌握位置化参数使用;
掌握 shell 中的特殊字符;
掌握常用的 shell 语句。
7.2 shell 变量
7.2.1 用户变量的定义
步骤 1
执行如下命令,设置自定义局部变量。
[root@openeuler ~]# dir=/usr/tmp/
[root@openeuler ~]# echo $dir
/usr/tmp/
[root@openeuler ~]# today=Sunday
[root@openeuler ~]# echo $today
Sunday
[root@openeuler ~]# echo $Today
//无回显
[root@openeuler ~]# str=“Hapy New Year!”
[root@openeuler ~]# echo “Wish You $str”
Wish You Hapy New Year!
###作为交互式输入手段,可以利用 read 命令由标准输入(即键盘)上读取数据,然后赋给指定的变量。
其一般格式是:read 变量 1 [变量 2…]
[root@openeuler ~]# read name
openeuler
//此处输入 openeuler
[root@openeuler ~]# echo $name
openeuler
[root@openeuler ~]# read a b cHCIA-openEuler 实验指导手册
第 118 页
kunpeng 2020 huawei
#此处输入 kunpeng 2020 huawei
[root@openeuler ~]# echo $a
kunpeng
[root@openeuler ~]# echo $b
2020
[root@openeuler ~]# echo $c
huawei
步骤 2
执行如下步骤,配置用户变量。
[root@openEuler ~]# vim .bash_profile
~/.bash_profile 是用户独享的配置文件
#在文件最后新增一行,修改完成后保存退出:
a=1000
[root@openEuler ~]# echo $a
#未更新变量文件时,a 值未发生变化
kunpeng
[root@openEuler ~]# source .bash_profile #更新变量文件后,a 值发生变化
[root@openEuler ~]# echo $a
1000
[root@openEuler ~]# bash
#打开一个新的 bash
[root@openEuler ~]# echo $a #a 变量未定义
[root@openEuler ~]# exit
#退出新打开的 shell
[root@openEuler ~]# su - root#以登录的方式切换用户,此时会自动读取.bash_profile 文件
[root@openEuler ~]# echo $a #a 变量值生效
1000
[root@openEuler ~]# exit
#退出当前的登录 shell
步骤 3
执行如下步骤,配置系统环境变量。
[root@openEuler ~]# vim /etc/profile
/etc/profile 是系统的配置文件,所有用户共享
#在文件最后新增一行,输入如下信息,并保存退出:
b=2000
[root@openEuler ~]# echo $b
#变量未更新
2020
[root@openEuler ~]# source /etc/profile
#更新变量
[root@openEuler ~]# echo $b
2000
#变量值发生了变化
[root@openEuler ~]# bash
#打开一个新的 bash
[root@openEuler ~]# echo $b #b 变量未定义
[root@openEuler ~]# exit
#退出新打开的 shell
[root@openEuler ~]# su - root#以登录的方式切换用户,此时会自动读取.bash_profile 文件
[root@openEuler ~]# echo $b #a 变量值生效
2000
[root@openEuler ~]# useradd huawei
#新增一个用户
[root@openEuler ~]# su - huawei
#切换到该用户
[huawei@openEuler ~]$ echo $b
2000
#变量 b 生效
[huawei@openEuler ~]$ exit
#退出当前用户
logoutHCIA-openEuler 实验指导手册
第 119 页
7.2.2 位置参数
步骤 1
在/root 目录下新建三个文件 m1.c、m2.c、ex1.sh,内容如下:
m1.c:
main()
{
printf(“Begin \n”);
}
m2.c:
include < stdio.h >
{
printf(“OK! \n”);
}
ex1.sh:
#!/bin/bash
ex1.sh: shell script to combine files and count lines
cat $1 $2 $3 $4 $5 $6 $7 $8 $9 | wc -l
end
步骤 2
执行脚本 ex1.sh。
[root@openeuler ~]# chmod u+x ex1.sh
[root@openeuler ~]# sh ex1.sh m1.c m2.c
8
7.3 shell 中的特殊字符
步骤 1
新建脚本 ex3.sh,写入如下内容:
#!/bin/bash
echo “current directory ispwd
”
echo “home directory is $HOME”
echo “file*.?”
echo " directory ‘$HOME’"
步骤 2
执行脚本 ex3.sh
[root@openeuler ~]# chmod u+x ex3.sh
[root@openeuler ~]# sh ex3.sh
current directory is ‘pwd’
home directory is /root
file*.?
directory ‘/root’
Linux 中其他特殊变量列表HCIA-openEuler 实验指导手册
第 120 页
变量
含义
$0
当前脚本的文件名
$n
传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参
数是$1,第二个参数是$2。
$#
传递给脚本或函数的参数个数。
$*
传递给脚本或函数的所有参数。
$@
传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将
会讲到。
$?
上个命令的退出状态,或函数的返回值。
$$
当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID
7.4 条件判断与循环结构
7.4.1 if 语句
7.4.1.1 语法示例
步骤 1
新建脚本 ex4.sh,写入如下内容:
#!/bin/bash
a=3
b=$1
if [ $a == $b ]
then
echo “You win!”
else
echo “Please guess again.”
fi
步骤 2
执行脚本 ex4.sh。
[root@openeuler ~]# chmod u+x ex4.sh
[root@openeuler ~]# ./ex4.sh 3
You win!
[root@openeuler ~]# ./ex4.sh 4
Please guess again.
7.4.1.2 【附录】if 常用判断
文件/目录判断
[ -a FILE ] 如果 FILE 存在则为真。
[ -b FILE ] 如果 FILE 存在且是一个块文件则返回为真。
[ -c FILE ] 如果 FILE 存在且是一个字符文件则返回为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。
[ -e FILE ] 如果 指定的文件或目录存在时返回为真。HCIA-openEuler 实验指导手册
第 121 页
[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。
[ -g FILE ] 如果 FILE 存在且设置了 SGID 则返回为真。
[ -h FILE ] 如果 FILE 存在且是一个符号符号链接文件则返回为真。(该选项在一些老系统上
无效)
[ -k FILE ] 如果 FILE 存在且已经设置了冒险位则返回为真。
[ -p FILE ] 如果 FILE 存并且是命令管道时返回为真。
[ -r FILE ] 如果 FILE 存在且是可读的则返回为真。
[ -s FILE ] 如果 FILE 存在且大小非 0 时为真则返回为真。
[ -u FILE ] 如果 FILE 存在且设置了 SUID 位时返回为真。
[ -w FILE ] 如果 FILE 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是
可执行的)
[ -x FILE ] 如果 FILE 存在且是可执行的则返回为真。
[ -O FILE ] 如果 FILE 存在且属有效用户 ID 则返回为真。
[ -G FILE ] 如果 FILE 存在且默认组为当前组则返回为真。(只检查系统默认组)
[ -L FILE ] 如果 FILE 存在且是一个符号连接则返回为真。
[ -N FILE ] 如果 FILE 存在 and has been mod 如果 ied since it was last read 则返回为
真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则返回为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 比 FILE2 新, 或者 FILE1 存在但是 FILE2 不存在则返回为
真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 老, 或者 FILE2 存在但是 FILE1 不存在则返回为
真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则返回为真。
字符串判断
[ -z STRING ] 如果 STRING 的长度为零则返回为真,即空是真
[ -n STRING ] 如果 STRING 的长度非零则返回为真,即非空是真
[ STRING1 ] 如果字符串不为空则返回为真,与-n 类似
[ STRING1 == STRING2 ] 如果两个字符串相同则返回为真
[ STRING1 != STRING2 ] 如果字符串不相同则返回为真
[ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则返回为真。
[ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则返回为真。
数值判断
[ INT1 -eq INT2 ] INT1 和 INT2 两数相等返回为真,=
[ INT1 -ne INT2 ] INT1 和 INT2 两数不等返回为真,<>
[ INT1 -gt INT2 ] INT1 大于 INT2 返回为真,>
[ INT1 -ge INT2 ] INT1 大于等于 INT2 返回为真,>=
[ INT1 -lt INT2 ] INT1 小于 INT2 返回为真,<
[ INT1 -le INT2 ] INT1 小于等于 INT2 返回为真,<=HCIA-openEuler 实验指导手册
第 122 页
逻辑判断
[ ! EXPR ] 逻辑非,如果 EXPR 是 false 则返回为真。
[ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。
[ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。
|| 用 OR 来合并两个条件
&& 用 AND 来合并两个条件
7.4.1.3 作业
编写一个脚本,该脚本可以判断当前用户是否为 root。
编写一个脚本,该脚本可以判断今天是否为休息日。
7.4.2 测试语句
步骤 1
新建脚本 ex5.sh,写入如下内容:
#!/bin/bash
echo “Please enter your filename:”
read filename
if [ -f “$filename” ]
then cat $filename
elif [ -d “$filename” ]
then cd $filename
pwd
ls -l -a
else echo “$filename:bad filename”
fi
步骤 2
执行脚本 ex5.sh。
[root@openeuler ~]# chmod u+x ex5.sh
[root@openeuler ~]# mkdir test
[root@openeuler ~]# sh ex5.sh
Please enter your filename:
test
/root/test
total 8
drwx------. 2 root root 4096 Feb 18 11:29 .
dr-xr-x—. 3 root root 4096 Feb 18 11:30 ..
[root@openeuler ~]# sh ex5.sh
Please enter your filename:
ex3.sh
echo “current directory is ‘pwd’”
echo “home directory is $HOME”
echo “file*.?”
echo “directory ‘$HOME’”
7.4.3 while 语句
步骤 1
新建脚本 ex6.sh,写入如下内容:HCIA-openEuler 实验指导手册
第 123 页
#!/bin/bash
while [ $1 ]
do
if [ -f $1 ]
then echo “display:$1”
cat $1
else echo “$1 is not a file name”
fi
shift
done
步骤 2
执行脚本 ex6.sh
[root@openeuler ~]# sh ex6.sh ex3.sh
display:ex3.sh
echo “current directory is ‘pwd’”
echo “home directory is $HOME”
echo “file*.?”
echo “directory ‘$HOME’”
[root@openeuler ~]# sh ex6.sh a
a is not a file name
7.4.4 for 语句
步骤 1
新建脚本 ex7.sh,写入如下内容:
#!/bin/bash
for Num in {1..10}
do
echo $Num
done
步骤 2
执行脚本 ex7.sh
[root@openeuler ~]# sh ex7.sh
1
2
3
4
5
6
7
8
9
10
步骤 3
新建一个 namefile 文件,写入如下内容:
user1
user2
user3HCIA-openEuler 实验指导手册
第 124 页
user4
步骤 4
新建脚本 ex8.sh,写入如下内容:
#!/bin/bash
for Name in $(cat ./namefile)
do
echo $Name
done
步骤 5
执行脚本 ex8.sh。
[root@openeuler ~]# sh ex8.sh
user1
user2
user3
user4
7.4.5 case 语句
步骤 1
新建脚本 ex9.sh,写入如下内容:
#!/bin/bash
echo ‘Input a number between 1 to 4’
printf ‘Your number is:\n’
read aNum
case $aNum in
- echo ‘You select 1’
;;
- echo ‘You select 2’
;;
- echo ‘You select 3’
;;
- echo ‘You select 4’
;;
*) echo ‘You do not select a number between 1 to 4’
;;
esac
步骤 2
执行脚本 ex9.sh。
[root@openEuler ~]# sh ex9.sh
Input a number between 1 to 4
Your number is:
1
You select 1
7.5 作业
1 反向输出HCIA-openEuler 实验指导手册
第 125 页
-
当用户输入 yes,显示 no
-
当用户输入 no,显示 yes
-
当用户输入其它,提示用户输入 yes/no
-
忽略大小写
新建用户
-
新建一个用户名列表 namefile
-
新建一个脚本,该脚本能够实现根据 namefile 自动创建用户,且密码随机生成。用户创
建后将用户名和密码导入到/root/loginname.txt 中。
- 随机密码生成可以使用:openssl rand -base64 6
脚本实现输出机器信息
-
将本机的网卡的 IP 地址和 MAC 地址截取出来,输出到/root/nic
-
将本机的磁盘使用情况截取出来 输出到 /root/disk
-
判断系统空间使用的情况,如果 / 使用率大于 30% 则删除 /tmp 的内容
测试用户是否存在,并判断是否是超级用户
- 写一个脚本:如果指定的用户存在,先说明其已经存在,并显示其 ID 号和 SHELL,并判
断是否是超级用户;否则,就创建用户,并显示其 ID 号
创建或目录文件
-
该脚本应当有交互功能
-
该脚本用于备份系统目录
-
需要给予用户提示,提示用户应当输入目录或者文件名
-
判断用户要备份的文件是否存在,如果不存在则告知用户,并输出相应错误
-
判断用户要备份的目标目录是否存在,如果该目录不存在,则需要问用户是否创建,如果
该目录已经存在,则需要问用户是否重命名该目录
测试 IP 是否可达
-
根据 iplist.txt 文件中列举的 IP 地址,判断 IP 地址是否可达。
-
只显示可达的 IP 地址。(不可达的可以使用 >> /dev/null)
输出名片
-
交互式输入自己信息,提示信息输入;
-
输入完成所有个人信息后,一次性打印出个人所有信息,并要求输出格式美观。