Linux shell脚本基础
一.基本介绍
shell脚本是包含一些命令或声明,并符合一定格式的文本文件,通常用于自动化常用命令,执行系统管理和故障排除,创建简单的应用程序,处理文本或文件。shell脚本在一定程度上可以理解为是将各类命令预先放入到一个文件中,方便一次执行的一个程序文件。shell脚本是纯文本文件,由于shell脚本每个脚本本身也是一个命令,所以使得shell脚本可以无限引用,也就使shell功能非常强大。
二.创建shell脚本
创建一个脚本的步骤:
1.创建shell脚本首先需要一个编辑文本的编辑器,通常我们使用vim。
2.在命名上我们一般使用简单明确的单词或缩写加上“.sh”后缀来命名
3.创建文件后第一行必须包括shell声明序列“#!”,并在后面跟上我们的shell来声明我们使用的shell
4.从第二行开始键入我们的命令也就是正式开始写脚本
5.写完脚本后,保存并退出,然后给予我们的shell脚本以执行权限
6.运行脚本
接下来我们来创建一个简单的shell脚本
创建并编写:
[root@centos7 ~]# vim helloworld.sh #!/bin/bash echo "hello world" echo "this is my first Shell Script"
解释:
第一行我用vim编辑器创建了一个名为“helloworld.sh”的文件(shell脚本)
第二行用“#!”来声明我用的shell是bash,而“/bin/bash”是其路径
第三行和第四行是我的命令,意思是输出引号中的字符
加入执行权限并执行:
[root@centos7 ~]# chmod a+x /root/helloworld.sh [root@centos7 ~]# /root/helloworld.sh hello world this is my first Shell Script
解释:
第一行我给予刚才创建的文件以执行权限
第二行我通过路径执行这个脚本
第三行和第四行是这个脚本执行的命令
通过上面的举例应该可以大致了解了如何去创建一个shell脚本
三.shell脚本的执行
shell脚本的执行方法有如下三种:
1.bash 脚本名 或者 sh 脚本名
这种方法可在脚本没有执行权限或者没有在开头指定shell时使用,其本质是调用bash/sh来执行后面的文件,也就是我们的脚本,不过这里是把脚本当做文件来看。bash/sh是shell也就是解释器。
2.路径
通过路径来执行脚本,需要执行权限,在上面的例子中我就是用路径来执行脚本的,这个路径可以是相对路径也可以是绝对路径.
3.source 脚本名 或者 .脚本名
source和“.”的意思是读入脚本并执行,通过这个方法执行脚本是在当前shell执行脚本,而上面的两种方法都是产生一个新的子shell来执行脚本。
在shell脚本运行后可能会因为各种语法错误,导致损坏系统,所以建议在执行脚本前先用下面的命令来检测语法的错误,仅检测而不执行
bash -n /路径/脚本名
在脚本提示报错后可用以下命令来调试脚本,打印出脚本的报错信息和每一步变量的值
bash -x /路径/脚本名
四.变量
变量的本质是一个命名的内存空间,在设置变量时,内存会将一定大小的空间赋予这个变量,并在之后重新赋值时改变这个空间的数据,调用时直接从这个空间读取数据,可简单的理解为变量是我们用来暂时存储一个数据的方式,我们可以为这个变量赋值为字符,整型和浮点型
1.变量命名法则:
不能使程序中的保留字:例如if, for
只能使用数字、字母及下划线,且不能以数字开头
见名知义
统一命名规则:驼峰命名法(每个单词首字母大写)
2.变量种类
局部变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
环境(全局)变量:生效范围为当前shell进程及其子进程
本地变量:生效范围为当前shell进程中某代码片断,通常指函数
位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命
令行传递给它的参数
特殊变量:$?, $0, $*, $@, $#,$$
3.局部变量
变量赋值:name=‘value’(例如我想将a赋值为1: a=1)
可以使用引用value:
(1) 可以是直接字符串; name=“root"
(2) 变量引用:name="$USER"($变量名 表示引用这个变量的值,此处的USER就是一个变量)
(3) 命令引用:name=`COMMAND` name=$(COMMAND)(``与$等效)
变量引用:${name} $name
“ ”:弱引用,其中的变量引用会被替换为变量值
‘ ’:强引用,其中的变量引用不会被替换为变量值,而保持原字符串
‘ ’与“ ”效果演示:
[root@centos7 ~]# a=123 [root@centos7 ~]# echo "a is $a" a is 123 [root@centos7 ~]# echo 'a is $a' a is $a
显示已定义的所有变量:set
删除变量:unset name
4.环境变量
变量声明、赋值(存入内存):
export name=VALUE
declare -x name=VALUE
由于是存入内存所以重启后需要重新配置,如果想写入硬盘可先在/etc/profile.d/下创建一个文件用来存储自己定义的变量并将上面的命令写入文件
变量引用:$name, ${name}
显示所有环境变量:
env
printenv
export
declare -x
删除变量:unset name
bash中的常用内建环境变量:
PATH 执行文件的路径
SHELL 默认shel
USER 当前用户
UID 当前用户uid
HOME 家目录
PWD 当前目录
LANG 默认字符集
MAIL 邮箱文件
HOSTNAME 主机名
HISTSIZE history记录命令的上限条数
RANDOM 随机数
SHLVL 当前shell级别
5.只读变量,特殊变量,位置变量
只读变量:只能声明,但不能修改和删除
– 声明只读变量:
readonly name
declare -r name
– 查看只读变量:
readonly –p
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ...:对应第1、第2等参数,shift [n] 销毁第n个参数默认为1,并将之后的参数前移
$0: 命令本身
$*: 传递给脚本所有参数,全部参数合为一个字符串
$@: 传递给脚本所有参数,每个参数为独立字符串
$#: 传递给脚本参数的个数
$@ $* 只在被双引号包起来的时候才会有差异
set -- 清空所有位置变量
特殊变量:
$$:当前进程的PID
$?: 上一个指令的返回值(0表示命令执行成功,1-255表示失败)
五.算数运算
bash中的算术运算:help let
+, -, *, /, %取模(取余), **(乘方)
实现算术运算:
(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 ...)
(5) declare –i var = 数值
(6) echo ‘算术表达式’ | bc
乘法符号有些场景中需要转义,如*
bash有内建的随机数生成器:$RANDOM(0-32767)
echo $[$RANDOM%50] :0-49之间随机数
六.赋值
增强型赋值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=3
自加3后自赋值
自增,自减:
let var+=1
let var++(同上)
let var-=1
let var--(同上)
七.条件测试(test)
判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用在条件性执行中
若执行成功即为真,则返回0
若执行失败即为假,则返回1
测试命令:
test命令可以和[ ]互相替换
test EXPRESSION 判断一个语句并返回布尔值
[ EXPRESSION ] 判断一个语句并返回布尔值
[[ EXPRESSION ]] 同上但内部使用正则
[[ +~ ]] =~后可以使用扩展正则表达式,注意正则表达式部分不能使用引号,判断一个变量或值是否符合=~后的正则类型
判断数值
[ a -eq b ] a是否等于b
[ a -ne b ] a是否不等于b
[ a -le b ] a是否小于等于b
[ a -lt b ] a是否小于b
[ a -gt b ] a是否大于b
[ a -ge b ] a是否大于等于b
判断字符串
[ $a == $b ] 判断两字符串是否一样
[ $a > $b ] a的ascii码是否大于b的ascii码
[ $a < $b ] a的ascii码是否小于b的ascii码
[ $a != $b ] a的ascii码是否不等于于b的ascii码
存在性及类别测试
test 判断 文件相关信息
test -a FILE:同-e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或-L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限
-s FILE: 是否存在且非空
-t fd: fd 文件描述符是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组
注意:EXPRESSION前后必须有空白字符
八.条件性的执行操作符
根据退出状态而定,命令可以有条件地运行
&& 代表条件性的AND THEN
|| 代表条件性的OR ELSE
例如:
grep-q no_such_user/etc/passwd || echo 'No such user'
No such user
ping-c1-W2 station1 &> /dev/null && echo "station1 is up"|| (echo 'station1 is unreachable'; exit 1)
station1 is up