Shell编程
Shell编程入门
认识Shell
开发者在进行服务器集群管理时,都需要编写 Shell 程序来进行服务器管理。Shell 是一个命令行解释器,为用户提供了一个向 Linux 内核发送请求以便于运行程序的界面系统升级程序。用户可以用 Shell 来启动、挂起、停止或者编写一些程序。
Shell 脚本的创建与执行
Shell 脚本在执行时有两个格式上的要求:以 #!/bin/bash 开头、必须有可执行权限。如下我们编写第一个 Shell 脚本:
- 创建新目录 shell 用于存放 shell 脚本;
1
2root@raspberrypi:~# mkdir /root/shell
root@raspberrypi:~# cd /root/shell/ - vim 编辑器新建 shell 脚本 shell.sh,输入命令;
1
2
echo "hello world!" - 这个时候查看 shell.sh 的权限,是没有可执行权限 x 的;

- 为它添加可执行权限;
1
root@raspberrypi:~/shell# chmod u+x shell.sh

- 执行文件;

shell 脚本常用的执行方式有两种:
- 输入脚本的绝对路径或者相对路径(需要先赋予脚本执行权限 x);
- sh + 脚本(无需赋予执行权限,直接执行即可)。
Shell 变量
系统变量和自定义变量
Linux Shell 中的变量分为系统变量和用户自定义变量。系统变量顾名思义就是系统已经设置好的变量,诸如 $HOME、$PWD、$USER、$SHELL 等都是系统变量。使用指令 set 可以查看系统中所有的系统变量。我们常用较多的是自定义变量,基本语法如下:
- 定义变量:_变量名称=值_;
- 撤销变量:_unset 变量名_;
- 定义静态变量:_readonly 变量名称=值_(静态变量不能撤销);
- 输出变量:_$变量_。
试着操作一下变量:
1 | #定义变量A |
执行结果为;
变量的基本规则
在定义变量时变量名称可以由字母、数字和下划线组成,但
- 不能以数字开头;
- 等号的两侧不能有空格;
- 变量名称一般为大写。
将命令的返回值赋给变量时使用如下写法;
- A=
data,表示运行中的命令,并把结果返回给 A; - A=$(data),$() 相当于 ``。
设置环境变量
- export 变量名=变量值 //将 Shell 变量输出为环境变量/全局变量
- source 配置文件 //让修改后的配置信息立即生效
- echo $变量名 //查询环境变量的值
案例:在 /etc/profile 文件中定义 TOMCAT_HOME 环境变量,vim 打开 /etc/profile 输入;
1 | export TOMCAT_HOME=/opt/tomcat |
设置完之后刷新配置状态;
1 | source /etc/profile |
结果如下;
位置参数变量
当执行一个 Shell 脚本时,如果希望获取到命令行的参数信息,就需要使用到位置参数变量。基本语法有:
1 | $n //n 为数字,$0 代表命令本身,$1-9 代表第 1 到第 9 个参数,10 以上的参数需要用大括号包含如 ${10} |
案例:编写一个 Shell 脚本 position.sh,在脚本中获取到命令行中的各个参数信息。
1 |
|
运行时输入 100 和 200 两个参数,结果如下。
预定义变量
预定义变量就是 Shell 的设计者事先定义好的变量,可以直接在 Shell 脚本中使用。基本语法有:
1 | $ //当前进程的进程号码(PID) |
运算符
1 | 在 Shell 编程中有各种运算操作,语法格式为 $((运算式))或 $[运算式] 或者 expr m + n;如果希望将 expr 的值赋给某个变量,使用 `` 即可。 |
- * //乘,在 `` 里面的乘应该用此格式即 * 前添加转义字符 \
- / //除
- % //取余
案例1:计算 (2+3)×4;
1 |
|
结果如下。
方式2报错了,原因如下:
$((...))是现代 bash 推荐的算术计算方式,语法简洁直观$[...]是较旧的语法,在某些 shell 中可能不支持expr是最传统的方式,需要注意运算符前后必须有空格,且某些运算符(如 *)需要转义
案例2:计算命令行两个参数的和;
1 | #计算命令行两个参数的和 |
运行时输入 20 和 50,结果如下:
条件判断
条件判断使用语法 **[ condition ]**(注意 condition 前后有空格),非空会返回 true。可以使用 $? 验证结果,0 为 true,>1 为false。如:
- [ hspEdu ] 会返回 true
- [ ] 会返回 false
- [ condition ] && echo yes || echo no ,前一个判断满足时会继续执行后面的语句
常用的判断语句有:
1 | 判断两个字符串 |
案例:判断 “ok” 是否等于 ok;
1 |
|
22 是否大于等于 21;
1 | if [ 22 -ge 21 ] |
/root/shell 目录下是否有 aaa.txt 文件;
1 | if [ -f /root/shell/aaa.txt ] |
执行结果如下:
流程控制
if 语句
if 语句的基本语法如下,需要注意 [ 条件判断式 ] 中括号与判断式之间必须有空格。
1 | #单分支 |
1 | #多分支 |
案例:编写一个 shell 程序,如果输入的参数大于等于 60,输出“及格”,小于 60 则输出“不及格”。
1 |
|
运行时带参数结果如下;
case 语句
基本语法如下,其中 * 代表都不是以上的值。
1 | case $变量名 in |
案例:编写 Shell 程序当命令行参数为 1 时输出“周一”,是 2 时输出“周二”,其他情况均输出“other”。
1 |
|
运行结果如下:
for 循环
for 循环有两个基本语法,语法一:
1 | for 变量 in 值1 值2 值3... |
案例1:打印命令行输入的参数;
1 |
|
运行结果如下,这也印证了 $*(将所有参数看成一个整体) 和 $@(将参数区别对待) 的区别;
除此之外 for 循环还有第二个语法;
1 | for((初始值;循环控制条件;变量变化)) |
案例2:输出从 1 加到 100 的值。
1 |
|

while 循环
基本语法:
1 | while [ 条件判断式 ] |
案例:命令行输入一个参数 n,计算 1+2+..+n 的值;
1 | #/bin/bash |
read 读取控制台输入
在我们进行 Shell 编程的时候,有时候也需要跟控制台进行交互,比如用户动态的输入一些数据,这个时候就需要用到 read。基本语法为
read(选项)(参数)
-p 制定读取值时的提示符
-t 指定读取值时的等待时间,如果没有在规定时间内输入,则不再等待
案例 1:读取控制台输入一个 num 值;
1 |
|

案例 2:读取控制台输入一个 num 值,指定在 10 秒内输入;
1 | read -t 10 -p "输入num2=" num2 |




