在linuxi系统与用户之间的解释器程序。默认为/bin/bash。
负责向内核翻译传达用户/程序指令。
位于系统内核与用户之间。
交互式:命令行,人工,逐条,效率低
非交互式:脚本,批量,后台,高效率 脚本一般使用非交互式指令
[[root@svr7 ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
1.命令历史:history
环境变量:
HISTSIZE:命令历史记录的条数
HISTFILE:~/.bash-history
HISTFILESIZE:命令历史文件记录历史的条数
控制命令历史的记录方式:
环境变量:HISTCONTROL
ignoredups:忽略重估的命令(连续且相同方为重复)
ignorespace:忽略所有以空白开头的命令
ignoreboth: ignoredups,ignorespace
2.命令补全:tab键
3.路径补全
4.命令行展开
~:展开为用户的主目录
~USERNAME:展开为指定用户的主目录
{}:可承载一个以逗号分隔的列表,并将其展开为多个路径
/tmp/{a,b} = /tmp/a , /tmp/b
/tmp/{a,b}/hi = /tmp/a/hi , /tmp/b/hi
5.命令执行结果状态
bash使用特殊变量$?保存最近一条命令的执行状态结果
echo $?:显示上一条命令执行的结果,返回0表示命令执行成功,返回1-255表示命令执行失败
6.别名:alias
7.glob(通配符)
bash中用于实现文件名通配,
通配符:
*:任意长度的任意字符
?:任意单个字符
[]:匹配指定范围内的任意单个字符
[0-9]:匹配数字
[a-z]:匹配字母,不区分大小写
[A-Z]:匹配大写字母
[^]:匹配指定范围外的任意单个字符
专用字符集合:
[:digit:]:任意数字,相当于0-9,若匹配数字,则[[:digit:]]
[:lower:]:任意小写字母
[:upper:]:任意大写字母
[:alpha:]:任意大小写字母
[:alnum:]:任意数字或字母
[:space:]:空格
[:punct:]:标点符号
8.快捷键
ctrl + l :清屏,相当于clear
ctrl + a:调到命令开始处
ctrl + e:跳到命令结尾处
ctrl + u:删除命令行首到光标所在处的内容
ctrl + k:删除光标至行尾的内容
9.> 重定向标准输出:命令正确的输出
2> 重定向错误输出:命令不正确输出
&> 重定向所有输出:不论什么类型,全部输出
[root@node-0001 shell]# ls yum.sh a
ls: 无法访问'a': 没有那个文件或目录 错误输出
yum.sh 标准输出
mount /dev/cdrom /mydvd &>/dev/null
提前写好的可执行程序,完成特定任务的文件。
顺序、批量化处理
是一种解释型程序。与Windows 的.bat文件相似。
shell 命名:Shell脚本名称命名一般为英文、大写、小写,后缀以.sh 结尾
不能使用特殊符号、空格
见闻之意,名称要写的一眼可以看出功能
shell 编程 首行需要 #!/bin/bash 开头
shell 脚本 变量 不能以 数字、特殊符号开头,可以使用下划线—,但不能 用破折号
shell 脚本运行前需要修改执行权限,需要以绝对路径执行
/opt目录下面随便使用
1、声明解释器 #!/bin/bash
2、编写注释 #描述脚本功能、变量作用等信息
3、编写执行指令 #使用非交互式的指令
chmod +x hello.sh
./hello.sh
bash ./hello.sh
source ./test.sh
1.单行注释:和python注释相同,以#
号开头作为单行注释
# 这是一个注释
2.多行注释:如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,可以将其定义为一个花括号的注释函数,也可以用多行注释
:<
把输入重定义到前面的命令,但是 : 是空命令,所以就相当于注释了。
如果注释中有反引号的命令就会报错,反引号部分不会被注释掉,例如var=ls -l
就不会被注释掉。
解决注释中反引号的问题
方法1: 注释外面加引号
:<
BLOCK 为 Here Documents 中的定义符号,名称任意,只要前后匹配就行。
[root@node-0001 shell]# vim hello.sh
#!/bin/bash
# first shell
echo 'hello world!!!'
[root@node-0001 shell]# chmod a+x hello.sh
[root@node-0001 shell]# ./hello.sh
#!/bin/bash
# This is echo color shell
# by author rivers 2021.09-23
# 字体颜色
for i in {31..37}; do
echo -e "\033[$i;40mHello world!\033[0m" #-e 使用转义字符
done
# 背景颜色
for i in {41..47}; do
echo -e "\033[47;${i}mHello world!\033[0m" #需要加双引号
done
# 显示方式
for i in {1..8}; do
echo -e "\033[$i;31;40mHello world!\033[0m"
done
常量: 固定不变的值
变量: 使用固定的名字存放可能发生变化的值,可以提高脚本的灵活度、适应力。
Shell变量名在定义时,首个字符必须为字母(a-z,A-Z),不能以数字开头,中间不能有空格,可以使用下划线(_),不能使用(-),也不能使用标点符号等。
#有效的变量
NAME
LIBRARY_PATH
_var
var2
#无效的变量
?var=123
user*name=ohuohuo
如果在变量中使用系统命令,需要加上 " `"符号(ESC键下方),如下所示
DATE1=`date`
DATE2=$(date) #二者功能相同
使用变量的时,用英文符号"$"
取变量值,对于较长的变量名,建议加上{ }
花括号,帮助解释器识别变量的边界,如下
name="test_name"
echo "My name is ${name}and you"
a=10 //创建变量(对变量赋值),名字是a,值是10
a=30 //再次赋值,之前的会被覆盖
echo $a //调用变量时使用$符号
unset a //取消变量的定义
a= //将变量a赋值为空,效果同上
echo ${a}RMB //变量名容易与后续字符发生混淆时使用大括号隔开
加上方括号时即所有便后面的语句不留空格,shell也会自动识别边界,默认添加USET一个空格.
已经定义过的变量,可以二次定义并重新被赋值覆盖上一次的变量值.
shell中的变量,默认为可读可写类型,如果想要其只可读,需要将其声明为**只读类型变量(**如同const
),使用readonly
命令
#!/bin/bash
Url="http://www.baidu.com"
readonly Url
删除变量,使用unset
,但是unset
不能删除只读变量.
#!/bin/sh
name="ohuohuo"
Url="http://www.baidu.com"
readonly Url # 设置只读变量
unset name # 可以被删除
unset Url # 不可被删除
echo $name # 不被打印出
echo $Url # 打印出
Shell编程中变量分为三种,分别是系统变量、环境变量和自定义变量。
env #查看环境变量
set #查看所有变量
Shell常见的变量之一系统变量,分为位置变量与预定义变量,主要是用于对参数判断和命令返回值判断时使用,系统变量详解如下:
$0 当前脚本的名称;
$n 当前脚本的第n个参数,n=1,2,…9; 常用于shell传参
$* 当前脚本的所有参数(不包括程序本身);
$# 当前脚本的参数个数(不包括程序本身);
$? 令或程序执行完后的状态,返回0表示执行成功;
$$ 程序本身的PID号。
$! 后台运行的最后一个进程的pid
[root@node-0001 shell]# cat \$.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
echo $*
echo $$
echo $#
echo $?
[root@node-0001 shell]# bash \$.sh a b c d
$.sh
a
b
c
a b c d
17416
4
0
Shell常见的变量之二环境变量,主要是在程序运行时需要设置,环境变量详解如下:
PATH #命令所示路径,以冒号为分割;
HOME #打印用户家目录;
SHELL #显示当前Shell类型;
USER #打印当前用户名;
ID #打印当前用户id信息;
PWD #显示当前所在路径;
TERM #打印当前终端类型;
HOSTNAME #显示当前主机名;
PS1 #定义主机命令提示符的;
HISTSIZE #历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间;
RANDOM #随机生成一个 0 至 32767 的整数;
HOSTNAME #主机名
PS1 #一级提示符 [\u@\h \W]
PS2 #二级提示符 >
用户变量又称为局部变量,主要用在Shell脚本内部或者临时局部使用。
a=rivers #自定义变量A;
Httpd_sort=httpd-2.4.6-97.tar #自定义变量Httpd_sort;
BACK_DIR=/data/backup/ #自定义变量BACK_DIR;
IPaddress=10.0.0.1 #自定义变量IPaddress;
1)" " 双引号 :用于界定范围
[root@node-0001 shell]# echo "ab cd"
2)’ ’ 单引号: 界定范围,屏蔽特殊符号的功能
[root@node-0001 shell]# echo '$USER'
$USER //无法调用变量,$被屏蔽
3)`` 反撇号: 获取命令的执行结果,还可以使用$( )实现相同效果
[root@node-0001 shell]# echo $(date)
[root@node-0001 shell]# echo `date`
#!/bin/bash
read -p "please input user name:" a
useradd $a
read -p "please input user passwd:" b
echo "$b" | passwd --stdin "$a"
echo $?
[root@node-0001 shell]# bash user.sh
please input user name:hehe
please input user passwd:xixi
更改用户 hehe 的密码 。
passwd:所有的身份验证令牌已经成功更新。
5)stty -echo 屏蔽显示输出 常用于设置密码时不显示密码
stty echo 显示屏幕输出
#!/bin/bash
read -p "please input user name:" a
useradd $a
stty -echo
read -p "please input user passwd:" b
echo "$b" | passwd --stdin "$a"
stty echo
[root@node-0001 shell]# bash user.sh
please input user name:hehe
please input user passwd:
更改用户 hehe 的密码 。
passwd:所有的身份验证令牌已经成功更新。
6)使用export发布全局变量
局部变量 仅仅在当前解释器进程中使用的变量
全局变量 解释器产生的子进程中也可以使用的变量
export a 声明全局变量 export -n a 取消全局变量
局部变量
root@node-0001 shell]# a=10
[root@node-0001 shell]# echo $a
10
[root@node-0001 shell]# bash
[root@node-0001 shell]# echo $a
全局变量
[root@node-0001 shell]# b=100
[root@node-0001 shell]# echo $b
100
[root@node-0001 shell]# export b
[root@node-0001 shell]# bash
[root@node-0001 shell]# echo $b
100
运算并输出结果
expr 1 + 1 //加法,运算符号两边要有空格
expr 2 '*' 2
expr 2 \* 2 // \是转义符号,可以屏蔽身后一个特殊符号的功能
a=10
b=20
expr $a + $b
expr $a + 100
expr $a + $a
运算,但不输出结果
$[1+1]
echo $[2*2]
echo $[2%2]
a=10
b=20
expr $a + $b
echo $[a+b]
echo $(($a+$b))
不输出,专用于变量的创建,或者变量的自增减
expr或 [ ] 、 []、 []、(())方式只进行运算,并不会改变变量的值;
而let命令可以直接对变量值做运算再保存新的值。
用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
let arg [arg ...]
自加操作:let no++
自减操作:let no–
简写形式 let no+=10,let no-=20,分别等同于 let no=no+10,let no=no-20。
# expr 实例
$ s=`expr 2 + 3`
$ echo $s
5
# let 实例
$ let s=(2+3)*4
$ echo $s
20
bc 交互式计算
[root@node-0001 shell]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
12.34+5.67
18.01
非交互式计算:
将需要运算的表达式通过管道操作交给bc运算。注意,小数位的长度可采用scale=N限制,除此以外也受参与运算的数值的小数位影响。
A.用echo和|法,如:
\# echo "(6+3)*2" |bc
18
\# echo 15/4 |bc
3
\# echo "scale=2;15/4" |bc
3.75
\# echo "3+4;5*2;5^2;18/4" |bc
还有ibase和obase来其它进制的运算。
//将16进制的A7输出为10进制, 注意,英文只能大写
\# echo "ibase=16;A7" |bc
167
//将2进制的11111111转成10进制
\# echo "ibase=2;11111111" |bc
255
//输入为16进制,输出为2进制
\# echo "ibase=16;obase=2;B5-A4" |bc
10001
可以赋予脚本智能判断的效果
语法格式 1, test 表达式 2, [ 表达式 ] 注意空格
== 两边是否相等,相等时条件测试算成功
!= 两边是否不等,不相等时条件测试算成功
[root@node-0001 shell]# man bc
[root@node-0001 shell]# test a == a
[root@node-0001 shell]# echo $?
0
[root@node-0001 shell]# [ a != b ]
[root@node-0001 shell]# echo $?
0
[root@node-0001 shell]# b=
[root@node-0001 shell]# [ -z $b ] # -z 判断变量是否为空
[root@node-0001 shell]# echo $?
0
[root@node-0001 shell]# [ -z $b ] # -z 判断变量是否为非空
条件 && 指令 条件成功才执行指令
条件 || 指令 条件失败才执行指令
当多个逻辑符号组合使用时
A && B && C A、B任务都成功才执行C
A && B || C A、B任务都成功不执行C
A || B && C A、B 任务有一个成功执行C
A || B || C A、B 任务有一个成功不执行C
${变量名:-初值} 定义变量时如果为空,调用时会使用初值
#!/bin/bash
read -p "请输入用户名:" u
[ -z $u ] && echo "必须输入用户名!" && exit
useradd $u
read -p "请输入密码(默认123456):" n
echo ${n:-123456} | passwd --stdin $u
shell使用运算符,需要结合其他命令和工具来使用(因为shell中不支持简单的数学运算),如使用算符运算符就需要搭配的常用的工具有两种
运算规则:
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | expr $a + $b 结果为 30。 |
- | 减法 | expr $a - $b 结果为 -10。 |
* | 乘法 | expr $a \* $b 结果为 200。 |
/ | 除法 | expr $b / $a 结果为 2。 |
% | 取余 | expr $b % $a 结果为 0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ $a != $b ] 返回 true。 |
需要注意的点:
shell中使用特殊的字符表示关系运算符,并且只支持数字,不支持字符串,除非字符串是数字.
运算符 | 说明 | 举例a=10 b=20 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | 检测两个数是否不相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
# 编写脚本,每2分钟检查服务器的用户数量,如果发生变化
#!/bin/bash
x=$(cat /etc/passwd | wc -l)
[ $x -gt 52 ] && echo "system is changed" | mail -s "test" root
[root@node-0001 shell]# crontab -e
*/2 * * * * /shell/user.sh
运算符 | 说明 | 举例a=10 b=20 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
运算符 | 说明 | 举例 a=10 b=100 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
运算符 | 说明 | 举例a=abc n=efg |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否不为 0,不为 0 返回 true。 | [ -n “$a” ] 返回 true。 |
$ | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
shell中的文件测试运算符用于检测在类unix系统中,文件的各种属性
操作符 | 说明 | 举例 |
---|---|---|
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 r权限对root无效 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 w权限对root无效 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 x权限对root有效 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
root@node-0001 shell]# ls -lh user.sh
-rwxr-xr-x. 1 root root 126 5月 7 14:34 user.sh
[root@node-0001 shell]# [ -d user.sh ] && echo "is"
not
[root@node-0001 shell]# [ -f user.sh ] && echo "is" || echo "not"
is
[root@node-0001 shell]# [ -r user.sh ] && echo "is" || echo "not"
is
[root@node-0001 shell]# [ -w user.sh ] && echo "is" || echo "not"
is
[root@node-0001 shell]# [ -x user.sh ] && echo "is" || echo "not"
is
[root@node-0001 shell]# [ -e user.sh ] && echo "is" || echo "not"
is
If条件判断语句,通常以if开头,fi结尾。也可加入else或者elif进行多条件的判断
# 单分支语句 ---比较大小
if (条件表达式);then
语句1
fi
# 双分支if 语句
if (表达式);then
语句1
else (表达式);then
语句2
fi
# 多支条件语句 ---判断成绩
if (表达式);then
语句1
elif (表达式);then
语句2
elif (表达式);then
语句2
fi
使用单分支语句判断crond 进程是否在运行
#!/bin/bash
# this is check crond
# by author rivers on 2021-9.23
# 定义一个变量名
name=crond
num=$(ps -ef|grep $name|grep -vc grep) #排除grep进程
if [ $num -eq 1 ];then
echo "$num running!"
else
echo "$num is not running!"
fi
判断主机是否连通
#!/bin/bash
ping -c 3 -i 0.2 -W 1 $1 &> /dev/null //使用$1位置变量更方便 -c 次数 -i 间隔时间 -w 不通返回时间
if [ $? -eq 0 ];then
echo "通了!"
else
echo "不通!"
fi
判断系统目录是否存在
#!/bin/bash
# this is check directory
if [ ! -d /data/rivers -a ! -d /tmp/rivers ];then
mkdir -p /data/rivers
fi
判断学生成绩等级
# if 语句可以直接对命令状态进行判断,就省去了获取$?这一步!
# 如果第一个条件符合就不再向下匹配
#!/bin/bash
# this check grade shell
grade=$1
if [ $grade -gt 90 ];then
echo "Is's very good!"
elif [ $grade -gt 70 ];then
echo "Is's is good!"
elif [ $grade -ge 60 ];then
echo "pass"
else
echo "no pass"
fi
#格式:for name [ [ in [ word ... ] ] ; ] do list ; done
for 变量名 in 取值列表
do
语句 1
done
in
列表中可以包含替换、字符串和文件名等
in
列表是可选的,如果默认不适用,将会循环使用命令行中的位置参数
for i in “file1” “file2” “file3”
for i in /boot/*
for i in /etc/*.conf
for i in $(seq -w 10) --》等宽的01-10
for i in $(seq -w 10 100) --》等宽的10-100
for i in {1…10} 1-10
for i in $( ls ) 当前目录
for i in $(< file) 文件内容 #以空格隔断
for i in “$@” --》取所有位置参数,可简写为for i
取值列表使用变量会报错,可以使用eval
#!/bin/bash
read -p "input:" x
s=0
for i in `eval echo {1..$x}`
do
let s+=i
done
echo $s
检查多台主机存活情况
#!/bin/bash
# check hosts is on/Off
Network=$1
for Host in $(seq 1 254)
do
ping -c 1 $Network.$Host > /dev/null && result=0 || result=1
if [ "$result" == 0 ];then
echo -e "\033[32;1m$Network.$Host is up \033[0m"
echo "$Network.$Host" >> /tmp/up.txt
else
echo -e "\033[;31m$Network.$Host is down \033[0m"
echo "$Network.$Host" >> /tmp/down.txt
fi
done
主要用于对某个数据域进行循环读取、对文件进行遍历,通常用于需要循环某个文件或者列表,满足循环条件会一直循环,不满足则退出循环,其语法格式以while…do开头,done结尾与
while 关联的还有一个 until 语句,它与 while 不同之处在于,是当条件表达式为 false 时才循环.
while (表达式)
do
语句1
done
exit 可以终止循环,但脚本也终止
break 可以终止循环,继续循环后的任务
continue 可以终止当前循环,继续下一次循环
continue与break 使用
#示例 1:在死循环中,满足条件终止循环
while true; do
let N++
if [ $N -eq 5 ]; then
break
fi
echo $N
done
输出: 1 2 3 4
#示例 2:举例子说明 continue 用法
N=0
while [ $N -lt 5 ]; do
let N++
if [ $N -eq 3 ]; then
continue
fi
echo $N
done
输出: 1 2 4
# 打印 1-100 数字
i=0
while ((i<=100))
do
echo $i
i=`expr $i + 1`
done
求1-100的总和
#!/bin/bash
# by author rivers on 2021-9-27
j=0
i=1
while ((i<=100))
do
j=`expr $i + $j`
((i++))
done
echo $j
until循环和while循环相反,知道条件不成立时才进行循环。条件成立,立即终止循环。
格式:
until 条件 #条件不成立进入循环
do
命令
done
#!/bin/bash
i=0
until ((i>100))
do
let sum+=$i
let i++
done
echo $sum
Case选择语句,主要用于对多个选择条件进行匹配输出,与if elif语句结构类似,通常用于脚本传递输入参数,打印出输出结果及内容。语法格式如下:
case 模式名 in
模式 1)
命令;;
模式 2)
命令;;
*)
不符合以上模式执行的命令;;
esac
每个模式必须以右括号结束,命令结尾以双分号结束。
httpd 服务启动脚本
[root@web-server01~/script]# vim httpd_start.sh
# check http server start|stop|starus
# by author rivers on 2021-9-27
while true
do
echo -e "
\033[31m start \033[0m
\033[32m stop \033[0m
\033[33m status \033[0m
\033[34m quit \033[0m
"
read -p "请输入你的选择start|stop|quit:" char
case $char in
start)
systemctl start httpd && echo "httpd服务已经开启" || echo "开启失败"
;;
stop)
systemctl stop httpd && echo "httpd服务已经关闭" || echo "关闭失败"
;;
restart)
systemctl restart httpd && echo "httpd服务已经重启" || echo "重启失败
"
;;
status)
systemctl status httpd && echo -e "
httpd 的服务状态
;;
quit)
select 是一个类似于 for 循环的语句
Select语句一般用于选择,常用于选择菜单的创建,可以配合PS3来做打印菜单的输出信息,其语法格式以select…in do开头,done结尾:
select i in (表达式)
do
语句
done
选择mysql 版本
#!/bin/sh
select ch in "begin" "end" "exit"
do
case $ch in
begin) echo "start something";;
end) echo "stop something";;
exit) exit;;
*) echo "error,input again";;
esac
done
打印lnmp选择菜单
#!/bin/bash
PS3="Please enter you select install menu:"
select i in http php mysql quit
do
case $i in
http)
echo -e "\033[31m Test Httpd \033[0m";;
php)
echo -e "\033[32m Test PHP\033[0m";;
mysql)
echo -e "\033[33m Test MySQL.\033[0m";;
quit)
echo -e "\033[32m The System exit.\033[0m";exit
esac
done
将一组命令集或语句形成一个可用块,这些块称为函数。
Shell编程函数默认不能将参数传入()内部,Shell函数参数传递在调用函数名称传递,例如name args1 args2。
函数语法
[ function ] funname [()]
{
action;
[return int;]
}
参数说明:
Shell 函数很简单,函数名后跟双括号,再跟双大括号,通过函数名直接调用,不加小括号。
#!/bin/bash
func() {
VAR=$((1+1))
return $VAR
echo "This is a function."
}
func
echo $?
所有的函数在使用前必须定义,这是因为shell解释器是顺序逐层执行的,当shell解释器发现定义的函数时,才会找到其对应的功能,进而执行。
使用shell函数传递参数时,需要在函数体的内部,通过 $n 的形式来获取参数的值,与其他语言不同的是,这不是在定义函数的时候就给定参数,而是在函数体中获取到的参数,例如,$1表示第一个参数,$2表示第二个参数,参数调用列表如下
参数处理 | 说明 |
---|---|
$# | 传递到脚本或函数的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数,空格隔开 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
#!/bin/bash
sum()
{
i=0
s=0
while ((i<$1+1))
do
let s+=i
let i++
done
echo "$s"
}
sum 100
sum 10
数组是相同类型的元素按一定顺序排列的集合。在bash下,仅仅支持一维数组,并且没有限定数组的大小,不支持多维数组。类似于 C 语言,数组元素的下标由 0 开始编号(上述字符串也是这样)。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
在 Shell 中,用括号( )
来定义表示数组,数组中元素用"空格"符号分割开。
格式:array=(元素 1 元素 2 元素 3 …)
用小括号初始化数组,元素之间用空格分隔。
定义方法 1:初始化数组 array=(a b c)
定义方法 2:新建数组并添加元素 array[下标]=元素
定义方法 3:将命令输出作为数组元素array=($(command))
array_name=(value1 value2 value3 value4)
array_test=(
value1
value2
value3
value4
)
array_text[0]=value0
array=($(command))
读取数组:和读取变量名相同,使用$
符号,需要加上下标名
valuen=${array_name[n]}
echo ${array_name[@]} # 读取所有
echo ${array_name[*]} # 取所有
获取数组长度:获取数组长度的方法与获取字符串长度的方法相同
# 取得数组元素的个数
length=${#array_name[@]} # 从头到尾取
# 或者
length=${#array_name[*]} # 取所有
# 取得数组单个元素的长度
lengthn=${#array_name[n]} # 取特定
#方法 1:
#!/bin/bash
IP=(10.0.0.1 10.0.0.2 10.0.0.3)
for ((i=0;i<${#IP[*]};i++)); do
echo ${IP[$i]}
done
# bash test.sh
10.0.0.1
10.0.0.2
10.0.0.3
#方法 2:
#!/bin/bash
IP=(10.0.0.1 10.0.0.2 10.0.0.3)
for IP in ${IP[*]}; do
echo $IP
done
在shell中字符串是shell编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。
# 使用单引号
str='this is a string'
# 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
# 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
#使用双引号
name="ohouhuoo"
str="please input your \"$name"\"
echo -e $str
# 可以在双引号中使用变量
# 可以在双引号中使用转义字符
1)计算字符串长度:在对变量进行取值时,使用" # "符号对字符串进行取值
${变量名称:截取位置:截取长度}
string="abcd"
echo ${#string} # 统计字符串长度
# 编写脚本,给用户生成随机密码
#!/bin/bash
echo >./user.txt #每次清空文本
str=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
for j in haha xixi lisi zhsan wangwu
do
pa=""
for i in {1..6}
do
sp=${str:$RANDOM%62:1}
pa=$sp$pa
done
echo "name:
passwd:$pa"&>>./user.txt
done
2)提取子字符串:使用字符串的截取命令,用于提取部分字符串。
索引从0开始,从第几个字符开始,取后面几个字符。
string="this is a test"
echo ${string:2:6} # 表示从第3个字符开始截取
3)替换字符串
格式: ${变量名/旧/新} 注意原始字符串并没有改变
a=1234
echo ${a/2/6} //将1个字符2换成6
a=112233
echo ${a/2/6} //将1个字符2换成6
echo ${a//2/6} //将所有字符2换成6
a=1122233
echo ${a/22/66} //换2个
echo ${a/11/} //将11替换成空,相当于删除
4)删除字符串
${变量名#要删除的内容} 掐头
${变量名%要删除的内容} 去尾 不能从中间开始
a=abcdef //创建变量,作为素材
echo ${a#abc} //掐头,从头删除abc
echo ${a##*c} //从左往右删除到最后1个c
echo ${a%d*} //去尾,从后删除def
echo ${a%%b*} //从右往左删除到最后1个b
a=abcdefghijk //创建变量,作为素材
echo ${a#*i} //效果同上,精简写法,将i及其前面的全部删除
echo ${a%defghijk} //去尾,删除到d
echo ${a%d*} //效果同上,精简写法,将d以及后面的删除
5)查找字符串:用于查找字符的位置,输出结果为字符在字符串中所占的数据位置,如果查找多个字符,那哪个字母先出现就计算哪个,如下查找it
中i
和t
两个字符,t
先出现,输出为1
string="this is a test"
echo `expr index "$string" it` # 输出 1
seq 用于生成从一个数到另一个数之间的所有整数。
用法:seq [选项]… 尾数 默认1开始
或:seq [选项]… 首数 尾数
或:seq [选项]… 首数 增量 尾数
选项:
-f, --format=FORMAT 使用 printf 风格的浮点 FORMAT
-s, --separator=STRING 使用 STRING 分隔数字(默认值:\n)
-w, --equal-width 通过用前导零填充来均衡宽度
seq 5
seq 5 10
seq 2 2 10
seq -s : 2 2 10
seq -w 10
输出1-100中,不包含数字7,且不能被7整除的数
seq 100 | grep -v "7" | awk '$0%7!=0{print}'
seq -f 'dir%03g' 1 5|xargs mkdir
#seq -f “%3g” 13 数字位数为三位,不足补空格
1
2
3
#seq -f “%03g” 1 5 数字位数为三位,不足补零
001
002
003
004
005
#seq -f "str%03g" 1 3
str001
str002
str003
可以用于在循环里生成要求的数。批量生成用户名或生成目录
seq -f 'tom%3g' 5
[root@develop shell]# a=tom
[root@develop shell]# seq -f '$a%g' 5