shell脚本基础
1.变量
1.1什么是变量
变量即可以变化的量
[root@lwq ~]# a=1
[root@lwq ~]# a=2
[root@lwq ~]# echo $a
2
1.2变量名称注意事项
- 只能包含字母,数字,下划线,并且不能以数字开头
- 不应该跟系统中已有的环境变量重名,尽量不要全部使用大写,尽量不要用“-”下划线开头
[rot@lwq ~]# ppp=1
[root@lwq ~]# echo $ppp
1
- 最好做到见名知义
- 不能使用程序中的保留字,例如if,for等
- 变量名区分大小写
- 变量名中有多个单词时有两种方法表示
- 单词间使用下划线分隔
- 首单词小写,后面单词的首字母大写
teacherName=tom
studentName=jerry
teacher_name=tom
student_name=jerry
变量作用:
保存表达式运算的结果至内存,方便复用或更改
若无变量而需复用表达式运算的结果只能重新运算,耗时较长
可以把变量理解为一个存储信息的容器
[root@lwq ~]# mkdir test;cd test;echo 'hello world' > abc
[root@lwq test]# ls
abc
[root@lwq test]# cat abc
hello world
[root@lwq ~]# a=$(pwd;ls)
[root@lwq ~]# echo $a
/root 2019.sh anaconda-ks.cfg
1.3变量类型
- 字符型
- 数值型
- 整型
- 浮点型
- 布尔型
1.4变量操作
- 设置变量
- 引用变量(单引号 双引号 $引用变量)
[root@lwq ~]# a=10
[root@lwq ~]# echo $a
10
[root@lwq ~]# echo '$a'
$a
[root@lwq ~]# echo "$a"
10```
[root@lwq ~]# cat > abc <<EOF
> $a
> bb
> cc
> EOF
[root@lwq ~]# cat abc
10
bb
cc
[root@lwq ~]# cat > abc <<'EOF'
> $a
> bb
> cc
> EOF
[root@lwq ~]# cat abc
$a
bb
cc
- 撤销变量
[root@lwq ~]# a=10
[root@lwq ~]# echo $a
10
[root@lwq ~]# unset a
[root@lwq ~]# echo $a
[root@lwq ~]#
1.5bash变量类型
- 环境变量
- 本地变量(局部变量)
- 位置变量
- 特殊变量(bash内置的,用来保存某些特殊数据的变量,也称系统变量)
1.5.1本地变量
- VAR-NAME=VALUE 本地变量(只在本地生效),作用域为当前shell进程。对当前shell外的其他进程,包括当前shell的父shell,子shell进程均无效
[root@lwq ~]# yum -y install psmisc
[root@lwq ~]# pstree
[root@lwq ~]# vim liu.sh
#!/bin/bash
teacher_name1=tom
teacher_name2=tom2
student_name1=jerry
student_name2=jerry2
echo $teacher_name1
[root@lwq ~]# bash liu.sh
tom
[root@lwq ~]# echo $teacher_name1
[root@lwq ~]# bash liu.sh
tom
- local VAR-NAME=VALUE 局部变量,作用域为当前代码段,常用于函数
1.5.2环境变量
export VAR-NAME=VALUE 作用域为当前shell进程及其子进程
[root@lwq ~]# export a=50
[root@lwq ~]# echo $a
50
[root@lwq ~]# bash
[root@lwq ~]# pstree
sshd───sshd───bash───bash───pstree
[root@lwq ~]# bash
[root@lwq ~]# bash
[root@lwq ~]# pstree
sshd───sshd───bash───bash───bash───bash───pstree
exit
1.5.3位置变量
$1,$2,$3,… 用来引用脚本的参数
shift [num] 位置变量使用完以后退出,后面的参数向前推进
[root@lwq ~]# vim 2019.sh
#!/bin/bash
lzy=$1
lan=$2
echo $lzy
echo -------
echo $lan
[root@lwq ~]# bash 2019.sh linux natasha
linux
-------
natasha
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
lzy=$1
lan=$2
qinggong=$3
shihao=$4
for i in $*;do
echo $lzy
echo $lan
echo $qinggong
echo $shihao
echo -----
shift 2
done
[root@lwq ~]# bash 2019.sh linux natasha qinggong shihao
linux
natasha
qinggong
shihao
-----
linux
natasha
qinggong
shihao
-----
linux
natasha
qinggong
shihao
-----
linux
natasha
qinggong
shihao
-----
[root@lwq ~]# vim liu.sh
#!/bin/bash
linux=$1
natasha=$2
ppp=$3
echo $linux
shift 2
echo $natasha
shift 2
echo $ppp
shift 2
[root@lwq ~]# bash liu.sh linux natasha
linux
natasha
1.5.4特殊变量
$# 是传给脚本的参数个数
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
echo $#
[root@lwq ~]# bash qinggong.sh
0
$0 是脚本本身的名字
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
echo $0
[root@lwq ~]# bash qinggong.sh 1 2 3 4
qinggong.sh
[root@lwq ~]# chmod +x qinggong.sh
[root@lwq ~]# ./qinggong.sh
./qinggong.sh
$! 是shell最后运行的后台Process进程的PID
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
a=1
echo $a
echo $!
[root@lwq ~]# bash qinggong.sh
1
$@ 是传给脚本的所有参数的列表
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
echo $@
[root@lwq ~]# bash qinggong.sh 1 2 3 4
1 2 3 4
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
echo $*
[root@lwq ~]# bash qinggong.sh 1 2 3 4
1 2 3 4
$$脚本运行当前进程id号
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
echo $$
[root@lwq ~]# bash qinggong.sh
8760
[root@lwq ~]# ps -ef | grep 8760
root 8762 8703 0 16:50 pts/0 00:00:00 grep --color=auto8760
[root@lwq ~]# vim qinggong.sh
#!/bin/bash
echo $$
sleep 600
[root@lwq ~]# bash qinggong.sh
8819
此时开一个终端
[root@lwq ~]# ps -ef | grep 8819
root 8819 8703 0 17:02 pts/0 00:00:00 bash qinggong.sh
root 8820 8819 0 17:02 pts/0 00:00:00 sleep 600
root 8824 8769 0 17:03 pts/1 00:00:00 grep --color=auto8819
[root@lwq ~]# kill -9 8819 8820
回第一个终端
[root@lwq ~]# bash qinggong.sh
8819
已杀死
$? 是显示上条命令的退出状态,0表示没有错误,其他表示有错误
1.5.5bash内建环境变量
- PATH
- SHELL
- UID
- HISTSIZE
- HOME
- PWD
- HISTFILE
- PS1
[root@lwq ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@lwq ~]# echo $SHELL
/bin/bash
[root@lwq ~]# echo $UID
0
[root@lwq ~]# echo $HISTSIZE
1000
[root@lwq ~]# echo $HOME
/root
[root@lwq ~]# echo $PWD
/root
[root@lwq ~]# echo $HISTFILE
/root/.bash_history
[root@lwq ~]# echo $PS1
[\u@\h \W]\$
[root@lwq ~]# PS1='[\lwq@liu\W]'
[1wq@liu~]bash
[root@lwq ~]# PS1='[\lwq@liu\qqq]'
[1wq@liu\qqq]bash
[root@lwq ~]#
1.5.6只读变量(常量)
readonly VAR-NAME=VALUE 不能修改值,不能销毁,只能等shell进程终止时随之消亡
[root@lwq ~]# readonly a=10
[root@lwq ~]# echo $a
10
[root@lwq ~]# a=20
-bash: a: 只读变量
[root@lwq ~]# echo $a
10
[root@lwq ~]# readonly a=20
-bash: a: 只读变量
[root@lwq ~]# unset a
-bash: unset: a: 无法反设定: 只读 variable
[root@lwq ~]# echo $a
10
[root@lwq ~]# exit
2.脚本基础
2.1什么是脚本
按实际需要,结合命令流程控制机制实现的源程序。说白点就是命令的堆砌。
2.2程序返回值
程序执行以后有两类返回值:
-
程序执行的结果
-
程序状态返回代码(0-255)
-
0:正确执行
[root@lwq ~]# echo $?
0
- 1-255:错误执行,1、2、127系统预留,有特殊意义
[root@lwq ~]# vim 88.sh
#!bin/bash
mkdir 100
cd 100/
touch 1 2 3
mkdir 4 5 6
[root@lwq ~]# bash 88.sh
[root@lwq 100]# ls
1 2 3 4 5 6
[root@lwq 100]# ls -l
总用量 0
-rw-r--r--. 1 root root 0 6月 12 11:06 1
-rw-r--r--. 1 root root 0 6月 12 11:06 2
-rw-r--r--. 1 root root 0 6月 12 11:06 3
drwxr-xr-x. 2 root root 6 6月 12 11:06 4
drwxr-xr-x. 2 root root 6 6月 12 11:06 5
drwxr-xr-x. 2 root root 6 6月 12 11:06 6
执行脚本方法:
1. bash+脚本名
2. /bin/bash+脚本名
3. chmod+x 脚本名
绝对路径+脚本名
4. chmod+x 脚本名
相对路径+脚本名
2.3脚本测试
bash -n scriptname //检查脚本是否有语法错误
bash -x scriptname //单步执行,检查脚本错在哪里
2.4写脚本注意事项
- 禁止将未成功执行过的代码直接写进脚本
- 脚本中的命令一定要用绝对路径
- (最好开两个终端,方便排错)
2.5shell算术运算
- let 算数运算表达式
let C=$A+$B
- $[ 算数运算表达式]
C=$[$A+$B]
[root@lwq ~]# vim 612.sh
#!/bin/bash
A=3
B=6
echo "$[$A+$B]"
[root@lwq ~]# bash 612.sh
9
- $((算数运算表达式))
C=$(($A+$B))
[root@lwq ~]# vim 612.sh
#!/bin/bash
A=3
B=6
echo "$(($A+$B))"
[root@lwq ~]# bash 612.sh
9
- expr算数运算表达式,表达式中各操作数及运算符之间要有间隔,而且要使用命令引用
C=`expr $A + $B`
[root@lwq ~]# vim 612.sh
#!/bin/bash
A=3
B=6
echo `expr $A + $B`
[root@lwq ~]# bash 612.sh
9
除法:
yum -y install bc
[root@lwq ~]# echo "scale=1;3/2"|bc
1.5
[root@lwq ~]# echo "scale=2;3/2"|bc
1.50
scale小数点后有几位
2.6命令间的逻辑关系
- 逻辑与:&&
第一个条件为假时,第二个条件不用再判断,最终结果已经有
第一个条件为真时,第二个条件必须得判断 - 逻辑或:| |
前一个命令的结果为真时,第二个命令就不执行
前一个命令的结果为假时,第二个命令就必须执行