Shell脚本
1.Shell的概念:
Shell的定义:
- Shell (外壳)是一个用C语言编写的程序,它是用户使用Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
- Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
什么时脚本:
- 脚本简单地说就是一条条的文字命令,这些文字命令是可以看到的(如可以用记事本打开查看、编辑)。
- 常见的脚本:JavaScript, VBScript,ASP, JSP, PHP, SQL, Perl, Shell, python, Ruby, JavaFX,Lua等。
为什么要学生和使用shell:
- 程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务
常见的shell种类:
在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本中函数的语法,Linux 中默认的shell是/bin/bash,流行的shell有ash、bash、 ksh、csh、 zsh等,不同的shell都有自己的特点以及用途。
①csh:c shell 使用的是“类C”语法,csh是具有C语言风格的一-种shell, 其内部命令有52个,较为庞大。目前使用的并不多,已经被/bin/tcsh 所取代。
②ksh:Korn shell的语法与Bourne shell 相同,同时具备了C shell的易用特点。许多安装脚本都使用ksh。ksh有42条内部命令,与bash有一定的限制性。
③tcsh:是csh的增强版,与C shell完全兼容。
④sh:是一个快捷方式,已经被/bin/bash 所取代。
⑤nologin:指用户不能登录
⑥zsh:目前Linux里最庞大的一种shell:zsh。 它有84个内部命令,使用起来也比较复杂。一般情况下,不会使用该shell.
⑦bash:大多数Linux系统默认使用的shell, bash shell是Bourne shell的一个免费版本,它是早的Unix shell, bash还有一个特点,可以通过help命令来查看帮助。包含的功能几乎可以涵盖shell所具有的功能,所以一般的shell脚本都会指定它为执行路径
2.Shell解析器:
| 特殊符号 | 功能 | 说明 |
|---|---|---|
| ; | 可使用分号分隔多条命令 | 在一行上输入和执行多条较短的命令,可使用分号来分隔命令 |
| * | 匹配任意零个或者多个字符 | 不能用于创建文件 |
| ? | 匹配任意单个字符 | 不能用于创建文件 |
| [] | 匹配方括号中的任意一个字符,表示范围可以用”-” | 不能用于创建文件 |
| [^]或者[!] | 匹配方括号中的任意一个字符或数字后进行取反 | 用于查找和删除文件,不用于创建文件 |
| {string,string} | 匹配括号中的任意一个字符串,表示一个范围时,字符串之间个”..” | 可用于创建、查看、删除文件 |
| \ s | 使\后面的特殊字符失s |
1.普通变量的定义与使用:
定义:(只对本次连接有效)
1
2class_name="yunsuanfu"
_name_4=$(cmd)使用:
1
echo $class_name # 输出class_name变量
变量名的规范:
注意,变量名后面的等号左右不能有空格,这可能和你熟悉的所有编程语言都不一样
变量名的命名须遵循如下规则:
命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线“_”。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。
双引号能够识别变量;单引号是不能识别变量,只会原样输出
双引号能够实现转义(类似于“*”);只会原样输出,单引号是不能转义的
2.环境变量的定义与使用:
环境变量也可称为全局变量,可以在创建它们的Shell 及其派生出来的任意子进程 Shell 中使用,环境变量又可分为自定义环境变量和 bash 内置的环境变量。
- bash内置的环境变量:用于定义 Shell 的运行环境,保证 Shell 命令的正确执行,Shell 通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等
- 自定义环境变量:自定义环境变量可以在命令行中设置和创建,但用户退出命令时这些变量值就会丢失。如果希望永久保存环境变量,可在用户家目录下的 .bash_profile 或 .bashrc 文件中,或者全局配置 /etc/bashrc 或 /etc/profile 文件中定义,在将环境变量放入上述的文件中后,每次用户登录时这些变量都将被初始化。
所有环境变量的名字均采用大写形式。
定义:
1
export 变量名=value
通过echo 或 printf 打印变量
1
2echo $HOME
显示默认的环境变量
1
2
3
4[root@www ~]$ env
XDG_SESSION_ID=17
HOSTNAME=www.oliven.com
TERM=xterm其他:
1
2
3
4[root@www ~]$ set
BASH=/bin/bash
[root@www ~]$ declare | head
BASH=/bin/bash用 unset 消除本地变量和环境变量
1
unset USER
3.命令别名:
别名是命令的快捷方式。对于需要经常执行,并需要很长时间输入的长命令创建快捷方式很有用
在命令行中使用alias命令设置的别名仅在该次登入有效,如果重新开启一个 Shell,或者重新登录
系统,则这些alias将无法使用。
语法
1
2
3alias 别名='原命令'
例:
alias myip="ip a | cut -d' ' -f6 | head -9 | tail -1"查看设置的别名:
1
alias
删除别名:
1
unalias 别名
在linux中提供alias永久化的方法:
- 若要让某个用户使用该别名,则把别名加在 ~/.bash_profile 或 ~/.bashrc 中。然后 source ~/.bashrc 或者 source ~/.bash_profile
- 若要让每一位用户都使用该别名,则把别名加在 /etc/bashrc 或者 /etc/profile 中,然后source /etc/bashrc 或者 source /etc/profile
4.命令历史:
history 命令可以查阅命令历史记录 ,也可在命令行利用向上或向下光标键来进行查询
语法:
1
2
3history [选项] [num]
例:
history 5 # 查询前5次的命令记录选项:
1
2
3
4
5number:显示最近number条命令历史
-c:清空当前历史命令
-a [file]:后面没跟文件时,默认将缓冲区中历史命令写入~/.bash_history中
-r [file]:将历史命令文件中的命令读入当前历史命令缓冲区中
-w:将当前历史命令缓冲区命令写入历史命令文件中;
5.内部命令:
echo可在屏幕上输出信息
echo参数选项 说明 -n 不换行输出内容 -e 解析转义字符 1
2[root@localhost ~]# echo -n i have a cat
i have a cat[root@localhost ~]#转义字符 说明 \n 换行 \r 回车 \t 制表符 \b 退格 \v 纵向制表符 1
2[root@localhost ~]# echo -e "i\thave\ta\tcat"
i have a cateval:当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新的命令,然后执行(以 ; 为分隔符换行输出数据)
1
2
3
4
5
6[root@localhost test]# a='shuju;head -1 /etc/passwd'
[root@localhost test]# echo $a
shuju;head -1 /etc/passwd
[root@localhost test]# eval echo $a
shuju
root:x:0:0:root:/root:/bin/bashexec:能够在不创建新的子进程的前提下,转去执行指定的命令,当指定的命令执行完毕后,该进程就终止了
export:设置或者显示环境变量
read:可从标准输入读取字符串等信息,传给shell程序内部定义的变量
参数 说明 p (prompt) 设置提示信息 -t (timeout) 设置输入等待时间,单位默认为秒 1
2[root@localhost test]# read -t 10 -p "please input your name:" name
please input your name:xiaoming1
2
3
4
5
6
7读取两个输入(以空格隔开),分别赋值给name1和name2
[root@localhost test]# echo -n "please input your name:";read name1 name2
please input your name:xiaoming xiaohong
[root@localhost test]# echo $name1
xiaoming
[root@localhost test]# echo $name2
xiaohongshift:在程序中每使用一次shift语句,都会使所有的位置参数依次向左移动一个位置,并使位置参数$#减1,直到减到0为止
exit:退出shell程序。在exit之后可以有选择地指定一个数作为返回状态
3.shell脚本入门:
1.编写规则:
代码规范: 作用:指定告知系统当前这个脚本要使用的shell解释器
1
2!/bin/bash
.......文件命名规范:文件名.sh .sh是linux下bash shell的默认后缀
开头加版本特权等信息
1
2
3
4
5# Date:创建日期
# Author:作者
# Mail:联系方式
# Function:功能
# Version:版本脚本中尽量不要用中文注释
多使用内部命令
1
常用的内部命令有:echo、eval、exec、export、read、shift、exit
2.配置vim的编辑格式:
针对单个用户:~/.vimrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19vim ~/.vimrc
内容
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#########################")
call setline(3,"#File name:".expand("%"))
call setline(4,"#Version:v1.0")
call setline(5,"#Email:1095322098@qq.com")
call setline(6,"#Created time:".strftime("%F %T"))
call setline(7,"#Description:")
call setline(8,"#########################")
call setline(9,"")
endif
endfunc
控制缩进格式为4个字符
autocmd FileType sh setlocal ai ts=4 sw=4 et针对所有用户:/etc/./vimrc
2.注释:
单行注释:
1
2comment1
comment2多行注释:
1
2
3:<<BLOCK
……注释内容
BLOCK
3.使用流程:
创建一个.sh文件
1
touch test.sh
编写shell代码
1
vim test.sh
1
2!/bin/bash
echo 'hello world!'执行shell脚本(脚本必须有执行权限)
1
./test.sh # 相对路径执行
1
/usr/local/app/test.sh # 绝对路径执行
4.执行脚本的方法:
查看进程:
1
ps -ef | grep pts/4
产生子进程,再运行,使用当前指定的bash shell去运行
1
bash ./filename.sh
产生子进程,再运行,使用脚本里面指定的shell去运行。使用该种方式执行需要权限
1
./filename.sh
(source命令是一个shell内部命令,其功能是读取指定的shell程序文件,并且依次执行其中的所有的语句,并没有创建新的子shell进程,所以脚本里面所有创建的变量都会保存到当前的shell里面
1
source ./filename.sh
和source一样,也是使用当前进程执行
1
. filename.sh
5.shell脚本的退出状态:
在UNIX或者Linux中,每个命令都会返回一个退出状态码。退出状态码是一个整数,其有效范围为0~255。
通常情况下,成功的命令返回0,而不成功的命令返回非0值。非0值通常都被解释成一个错误码
Shell脚本中的函数和脚本本身也会返回退出状态码。
在脚本或者是脚本函数中执行的最后的命令会决定退出状态码。
1
2./test1.sh
echo $?另外,用户也可以在脚本中使用exit语句将指定的退出状态码传递给Shell
1
4.变量:
1.变量名的规范:
注意,变量名后面的等号左右不能有空格,这可能和你熟悉的所有编程语言都不一样
变量名的命名须遵循如下规则:
命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线“_”。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。
双引号能够识别变量;单引号是不能识别变量,只会原样输出
双引号能够实现转义(类似于“*”);只会原样输出,单引号是不能转义的
2.变量的类型:
根据数据类型分类:
Shell是一种动态类型语言和弱类型语言,即在Shell中,变量的数据类型毋需显示地声明,变量的数据类型会根据不同的操作有所变化。
准确地讲,Shell中的变量是不分数据类型的,统一地按照字符串存储。
但是根据变量的上下文环境,允许程序执行一些不同的操作,例如字符串的比较和整数的加减等等
什么是弱类型语言、强类型语言:
- 强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远都是这个类型
- 弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,例:js中的var和let
declare命令还可输出所有的变量、函数、整数和已经导出的变量
参数:
参数 说明 -p 显示所有变量的值 -i 将变量定义为整数,在之后就可以直接对表达式求值,结果只能是整数。如果求值失败或者不是整数,就设置为0 -r 将变量声明为只读变量。只读变量不允许修改,也不允许删除。(也可使用readonly定义只读变量) -a 变量声明为数组变量。但这没有必要,所有变量都不必显示定义就可以用作数组。事实上,在某种意义上,似乎所有变量都是数组,而且赋值给没有下标的变量与赋值给下标为0的数组元素相同 -f 显示所有自定义函数,包括名称和函数体 -x 将变量设置成环境变量。可使用+x将变量变成非环境变量
根据作用域分类:
环境变量:
自定义环境变量:
一般是指用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,即该环境变量只在当前shell和子shell中有效。如果希望永久保存环境变量,可以在配置文件中设置
自定义环境变量的配置文件
1
2
3
4用户的环境变量配置(non-login shell)
~/.bash_profile或~/.bashrc
全局环境变量的配置(login shell)
/etc/bashrc、/etc/profile文件或者/etc/profile.d目录中定义注意:按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用命令export导出。
有一些环境变量,比如HOME,PATH,SHELL,UID,USER等,在用户登录前就已经被/bin/login程序设置好了
通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中
bash内置的环境变量:
shell内置的环境变量是所有的shell程序都可以使用的变量。shell程序在运行时,都会接收一组变量来确定登录用户名、命令路径、终端类型、登录目录等,这组变量就是环境变量。环境变量会影响到所有的脚本的执行结果
内置的环境变量:
变量 说明 PATH 命令搜索路径,以冒号为分隔符 HOME 用户主目录的路径名,是cd命令的默认参数 COLUMNS 定义了命令编辑模式下可使用命令行的长度 HISTFILE 命令历史文件 HISTSIZE 命令历史文件中最多可包含的命令条数 HISTFILESIZE 命令历史文件中包含的最大行数 IFS 定义shell使用的分隔符 LOGNAME 当前的登录名 SHELL shell的全路径名 TERM 终端类型 TMOUT shell自动退出的时间,单位为秒,若设为0则禁止shell自动退出 PWD 当前工作目录 注:可使用env查看环境变量
普通变量:
- 普通变量也可称为局部变量,与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访问,例如函数内部。
- 在Shell语言中,可以在函数内部通过local关键字定义局部变量,另外,函数的参数也是局部变量
3.变量的定义与使用:
变量定义示例:变量名=变量值
普通变量的定义:
1
2
3
4
5
6
7
8
9定义数值变量
a=1
定义字符串变量
[变量]="yunsuanfu"
定义备份路径
bak_dir=/data/backup
把一个命令的结果赋值变量
变量名=`ls`
变量名=$(ls)只读变量的定义
1
readonly a=10
接受用户输入:
1
2read -p [提示信息] [变量名]
# 例:read -p "请输入需要创建的文件路径:" filePath变量的删除:
1
unset [变量]
将变量转换成环境变量
1
2
3export mydata2=mydata2
mydata=mydata;export mydata
declare -x mydata3=mydata3
位置参数和预定义变量:
许多情况下,Shell脚本都需要接收用户的输入,根据用户输入的参数来执行不同的操作
从命令行传递给Shell脚本的参数又称为位置参数,Shell脚本会根据参数的位置使用不同的位置参数变量读取它们的值:
变量 说明 $# 命令行参数的个数 $n 表示传递给脚本的第n个参数,例如$1表示第一个参数,$2表示第二个参数,$3表示第三个参数 $0 当前脚本的名称 $* 以”参数1 参数2 参数3…”的形式返回所有参数的值 $@ 以“参数1”“参数2”“参数3”…的形式返回所有的值 $? 前一个命令或者函数的返回状态码 $$ 返回本程序的进程ID(PID),不常用 $! 获取上一个在后台工作的进程的进程号,不常用 $_ 保存之前执行的命令的最后一个参数,不常用 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13echo "第1个位置参数是$1"
echo "第2个位置参数是$2"
echo "所有参数是: $*"
echo "所有参数是: $@"
echo "参数的个数是: $#"
echo "当前进程的PID是: $$"
[root@localhost test]# bash param.sh shuju1 shuju2
第1个位置参数是shuju1
第2个位置参数是shuju2
所有参数是: shuju1 shuju2
所有参数是: shuju1 shuju2
参数的个数是: 2
当前进程的PID是: 232781
2
3
4
5
6
7
8
9
10!/bin/bash
ping -c2 $1 &> /dev/null
if [ $? = 0 ];then # $?为上一个命令或函数返回的状态码
echo "host $1 is ok"
else
echo "host $1 is fail"
fi
[root@localhost test]# chmod a+rx ping.sh
[root@localhost test]# ./ping.sh 192.168.168.128
host 192.168.168.128 is ok1
2
3
4
5
6[root@localhost test]# for i in "$*";do echo $i;done
i have a cat
[root@localhost test]# for i in "$@";do echo $i;done
i have
a
cat1
2
3
4
5
6[root@localhost test]# shift #使用该指令可将位置参数左移一位
[root@localhost test]# echo $1
a
[root@localhost test]# shift
[root@localhost test]# echo $1
cat
4.shell中变量的引用:
在bash中有很多特殊字符,这些特殊字符就具有特殊含义。引用就是通知shell将这些特殊字符当作普通字符来处理。
符号 说明 转义字符 “\” 如果将\放到特殊字符前面,shell就忽略这些特殊字符的原有含义,把它们当作普通字符对待 单引号 如果将字符串放到一对单引号之间,那么字符串中所有字符的特殊含义被忽略 双引号 双引号的引用与单引号基本相同,包含在双引号内的大部分特殊字符可以当作普通字符处理,但是仍然有一些特殊字符保留自己的特殊含义,比如”$“和“\”以及“ ` ” 1
2
3
4[root@localhost ~]# echo "current_user is: $USER" # 双引号中的$没有被忽略
current_user is: root
[root@localhost ~]# echo 'current_user is: $USER' # 单引号中的$被忽略
current_user is: $USER说明:反引号中的字符串将被解释为shell命令
1
2
3
4[root@localhost ~]# echo "current_user is: `whoami`" # 双引号中的反引号字符串被解释为shell命令
current_user is: root
[root@localhost ~]# echo 'current_user is: `whoami`' # 单引号中的反引号字符串被忽略
current_user is: `whoami`
4.1.转义符
| 转义字符 | 说明 |
|---|---|
| \n | 换行 |
| \r | 回车 |
| \t | 制表符 |
| \b | 退格 |
| \v | 纵向制表符 |
| \f | 换页符 |
6.变量的运算:
| 算数运算符 | 说明 |
|---|---|
| +、- 、*、/、% | 求和、差、乘积,商,余数 |
| ** | 幂运算,例如3**3是求3的立方,即27 |
| +=、-=、*=、/=、%= | 例a+=1相当于a=a+1 |
| ++variable、–variable | 先将变量variable的值加1,然后再赋给variable; 先将变量variable的值减1,然后再赋给variable |
| 位运算符<<、>> | |
| &、| ,~,^ | 按位与:1和1为1,其他为0;按位或:只要有1即为1,否则为0;按位非;按位异或:相同为1 |
条件表达式要放在方括号之间,并且要有空格
1
[$a == $b]
多原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr , expr最常用
运算命令 意义 说明 (()) 用于整数运算的常用运算符 在(())中使用变量时可以去掉变量前的$符号 let 用于整数运算 使用let命令可以执行一个或者多个算术表达式,其中的变量名毋需使用$符号 expr 可用于整数运算 使用expr时,运算符及用于计算的数字左右都至少有一个空格 bc 适合整数及小数运算 $[] 用于整数运算 awk 既可以整数也可以用于小数 declare 1
2
3
4
5
6
7
8
9
10num1=10
num2=2
echo "two bracket is $(($num1+$num2))" # (())用于整数运算的常用运算符
let num3=$num1*$num2 # let用于整数运算
echo "let is $num3"
echo "expr is `expr $num1 \| $num2`" # expr可用于整数运算
echo "square bracket is $[$num2**$num1]" # $[]用于整数运算
declare -i num4=$num1/$num2 # declare -i定义整形变量,做运算
echo "declare is $num4"
echo -n "bc is ";echo "$num2 / $num1" | bc # bc:seq生成数字序列(这里是1~10),-s指定分隔符(这里是+)1
awk 'BEGIN {print 2+3*2}' # awk既可以整数也可以用于小数
expr是一款表达式计算工具,使用它能完成表达式的求值操作:(注意使用的是反引号)
1
2val='expr2 + 2'
num3=`expr \( 2 + 3 \) \* 4` # 使用expr在遇到除"+,-"之外,都需要加转义符"\"
7.${ }表达式:
| 表达式 | 说明 |
|---|---|
| ${parameter} | 返回变量的内容 |
| $ |