什么是Shell脚本?
示例
打开文本编辑器(可以使用 vi/vim
命令来创建文件),新建一个文件 test.sh
,扩展名为 sh
(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用 php
写 shell
脚本,扩展名就用 php
好了。
1 | !/bin/sh |
示例解释
- 第1行: 指定脚本解释器, 这里用
/bin/sh
做解释器的 - 第2行: 切换到当前用户的
home
目录 - 第3行: 创建一个目录
shell_test
- 第4行: 切换到
shell_test
目录 - 第5行: 循环条件, 一共循环10次
- 第6行: 创建一个test_0…9.txt文件
- 第7行: 循环体 结束
“#!”
是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行。
示例结果
1 | [root@caoxl ~]# ls |
Shell和Shell脚本的概念
shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
shell脚本(shell script) ,是一种为shell
编写的脚本程序。业界所说的shell
通常都是指shell
脚本,但读者朋友要知道,shell
和shell script
是两个不同的概念。
Shell编程环境
shell
编程跟java
、php
编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
脚本解释器
sh
即Bourne shell
,POSIX(Portable Operating System Interface)标准的shell
解释器,它的二进制文件路径通常是/bin/sh
,由Bell Labs开发。
bash
Bash
是Bourne shell
的替代品,属GNU Project,二进制文件路径通常是/bin/bash
。业界通常混用bash
、sh
、和shell
,比如你会经常在招聘运维工程师的文案中见到:熟悉Linux Bash编程,精通Shell编程。
在CentOS
里,/bin/sh
是一个指向/bin/bash
的符号链接:
1 | [root@caoxl ~]# ls -l /bin/*sh |
但在Mac OS
上不是,/bin/sh
和/bin/bash
是两个不同的文件,尽管它们的大小只相差100字节左右:
1 | -r-xr-xr-x 1 root wheel 623344 9 30 04:28 /bin/bash |
运行Shell脚本的方法
作为可执行程序
1 | chmod +x ./test.sh #使脚本具有执行权限 |
作为解释器参数
直接运行解释器,其参数就是 shell 脚本的文件名,如:
1 | /bin/sh test.sh |
Shell 基础
Shell 变量
定义变量
定义变量时,变量名不加美元符号($,PHP语言中变量需要),如:
1 | var="bar" |
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用bash里的关键字(查看保留关键字)
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
1 | your_name="caoxl" |
只读变量
使用 readonly
命令可以将变量定义为只读变量,只读变量的值不能被改变。
1 | #!/bin/bash |
删除变量
使用 unset 命令可以删除变量。语法:
1 | unset variable_name |
Shell 字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单双引号的区别跟PHP类似。
单引号
1 | str='this is a string' |
双引号
1 | your_name='caoxl' |
双引号的优点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
拼接字符串
1 | your_name="caoxl" |
获取字符串长度
1 | string="abcd" |
提取子字符串
以下实例从字符串第 2
个字符开始截取 4
个字符:
1 | string="caoxl is a great site" |
Shell 数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
定义数组
在 Shell 中,用括号来表示数组,数组元素用”空格”符号分割开。定义数组的一般形式为:
1 | 数组名=(值1 值2 ... 值n) |
读取数组
读取数组元素值的一般格式是:
1 | ${数组名[下标]} |
使用 @
符号可以获取数组中的所有元素,例如:
1 | echo ${array_name[@]} |
获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同,例如:
1 | # 取得数组元素的个数 |
Shell注释
以 #
开头的行就是注释,会被解释器忽略。
通过每一行加一个 #
号设置多行注释,像这样:
1 | #-------------------------------------------- |
多行注释
多行注释还可以使用以下格式:
1 | :<<EOF |
EOF 也可以使用其他符号:
1 | :<<' |
Shell 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
1 | #!/bin/bash |
为脚本设置可执行权限,并执行脚本,输出结果如下所示:
1 | [root@caoxl shell]# vi params.sh |
另外,还有几个特殊字符用来处理参数:
|参数处理|说明|
|:—-|–:–|
|$#
|传递到脚本的参数个数|
|$*
|以一个单字符串显示所有向脚本传递的参数。如”$*”用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数。|
|$$
|脚本运行的当前进程ID号|
|$!
|后台运行的最后一个进程的ID号|
|$@
|与$*相同,但是使用时加引号,并在引号中返回每个参数。如”$@”用「”」括起来的情况、以”$1” “$2” … “$n” 的形式输出所有参数。|
|$-
|显示Shell使用的当前选项|
|$?
|显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。|
1 | #!/bin/bash |
执行脚本,输出结果如下所示:
1 | [root@caoxl shell]# chmod +x params2.sh |
Shell 函数
linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
shell中函数的定义格式如下:
1 | [ function ] funname [()] |
说明:
- 可以带
function fun()
定义,也可以直接fun()
定义,不带任何参数。 - 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
Shell 输入/输出重定向
命令 | 说明 |
---|---|
command > file |
将输出重定向到 file。 |
command < file |
将输入重定向到 file。 |
command >> file |
将输出以追加的方式重定向到 file。 |
n > file |
将文件描述符为 n 的文件重定向到 file。 |
n >> file |
将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m |
将输出文件 m 和 n 合并。 |
n <& m |
将输入文件 m 和 n 合并。 |
<<tag |
将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。