大家好,欢迎来到IT知识分享网。
输入输出重定向
linux 的标准输入与输出
设备 | 设备名 | 文件描述符 | 类型 |
---|---|---|---|
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/stdout | 1 | 标准输出 |
显示器 | /dev/stderr | 2 | 标准错误输出 |
输入重定向
输入重定向:是指不使用系统提供的标准输入端口,而进行重新的指定。换言之,输入重定向就是不使用标准输入端口输入文件,而是使用指定的文件作为标准输入设备。(重定向简单理解就是使用 “<”符来修改标准输入设备)
类型 | 符号(语法) | 功能 |
---|---|---|
标准输入 | 命令<文件1 | 命令把文件1的内容作为标准输入设备 |
标识符限定输入 | 命令<<标识符 | 命令把标准输入中读入内容,直到遇到“标识符”分解符为止 |
输入输出重定向(同时使用) | 命令< 文件1 >文件2 | 命令把文件1的内容作为标准输入,把文件2作为标准输出。 |
输出重定向
输出重定向:(通俗的讲,重定向输出就是把要输出的文件信息写入到一个文件中去,而不是将要输出的文件信息输出到控制台(显示屏),在linux中,默认的标准输出设备是控制台(或称为显示器),用户输出的信息默认情况下都会显示到控制台
&表示全部文件,文件不管对错,1表示标准输出文件,2表示标准错误输出。
类型 | 符号 | 作用 |
---|---|---|
标住输出重定向 | 命令 > 文件 | 以覆盖方式,把命令的正确输出内容输出到指定的文件或设备当中 |
标住输出重定向 | 命令 >> 文件 | 以追加方式,把命令的正确输出内容输出到指定的文件或设备当中 |
标准错误输出重定向 | 错误命令2 > 文件 | 以覆盖方式,把命令的错误输出输出到指定的文件或设备当中 |
标准错误输出重定向 | 错误命令2 >> 文件 | 以追加方式,把命令的错误输出输出到指定的文件或设备当中 |
正确输出和错误输出同时保存 | 命令 > 文件 2>&1 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 >> 文件 2>&1 | 以追加的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 &> 文件 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 &>> 文件 | 以追加的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 >> 文件1 2>>文件2 | 把正确的输出追加到文件1中,把错误的输出追加到文件2中。 |
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到/dev/null中
[root@localhost ~]$ command > dev/null
多命令顺序执行
多命令执行符 | 作用 | 格式 |
---|---|---|
; | 命令1 ;命令2 | 多个命令顺序执行,命令之间没有任何逻辑联系 |
&& | 命令1 && 命令2 | 当命令1正确执行( |
?
=
0
)
,
则
命
令
2
才
会
执
行
当
命
令
1
执
行
不
正
确
(
?=0),则命令2才会执行 当命令1执行不正确(
?
≠
0
)
,
则
命
令
2
才
会
执
行
当
命
令
1
正
确
执
行
(
?≠0),则命令2才会执行当命令1正确执行(
?=0),则命令2才会执行当命令1正确执行(?=0),则命令2不会执行 |
shell脚本的执行
[root@localhost ~]$ vim test.sh #!/bin/bash echo “hello world”
两种方式执行shell脚本
第一种:给文件增加执行权限
[root@localhost ~]$ chmod u+x test.sh [root@localhost ~]$ ./test.sh #绝对路径或相对路径执行
第二种(了解):通过Bash调用执行脚本
[root@localhost ~]$ bash test.sh
三、shell变量
什么是变量?
在一个脚本周期内,其值可以发生改变的量就是变量。
1. 变量的命名规则:
在定义变量时,有一些规则需要遵守:
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 等号左右两侧不能有空格,可以使用下划线“_”,变量的值如果有空格,需要使用单引号或双引号包括。如:“test=“hello world!””。其中双引号括起来的内容“$”,“(”和反引号都拥有特殊含义,而单引号括起来的内容都是普通字符。
- 不能使用标点符号,不能使用bash里的关键字(可用help命令查看保留关键字)。
- 环境变量建议大写,便于区分
- 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含” 变量名 ” 或用 变量名”或用 变量名“或用{变量名}包含变量名。
[root@localhost ~]$ test=123 [root@localhost ~]$ test="$test"456 [root@localhost ~]$ echo $test #叠加变量test,变量值变成了 [root@localhost ~]$ test=${test}789 [root@localhost ~]$ echo $test #再叠加变量test,变量值编程了
关于单双引号的问题:
双引号能够识别变量,双引号能够实现转义(类似于“\*”)
单引号是不能识别变量,只会原样输出,单引号是不能转义的
shell中特殊符号
符号 | 作用 |
---|---|
’ ’ | 单引号。在单引号中所有的特殊符号,如“$”和”(反引号)都没有特殊含义。单引号括起来的都是普通字符,会原样输出 |
“ ” | 双引号。在双引号中特殊符号都没有特殊含义,但是“$”,“`”(esc键下面)和“\”是例外,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义。 |
· · | 反引号。反引号括起来的内容是系统命令,在Bash中会先执行它。和 |
(
)
作
用
一
样
,
不
过
推
荐
使
用
()作用一样,不过推荐使用
单引号和双引号
[root@localhost ~]$ name=sc #定义变量name 的值是sc(就是最正直的人,超哥我了!) [root@localhost ~]$ echo '$name' $name #如果输出时使用单引号,则$name原封不动的输出 [root@localhost ~]$ echo "$name" sc #如果输出时使用双引号,则会输出变量name的值 sc [root@localhost ~]$ echo `date` 2018年10月21日星期一18:16:33 CST #反引号括起来的命令会正常执行 [root@localhost ~]$ echo '`date`' `date` #但是如果反引号命令被单引号括起来,那么这个命令不会执行,―date`会被当成普通字符输出 [root@localhost ~]$ echo "`date'" 2018年10月21日星期一18:14:21 CST #如果是双引号括起来,那么这个命令又会正常执行
反引号
[root@localhost ~]$ echo ls ls #如果命令不用反引号包含,命令不会执行,而是直接输出 [root@localhost ~]$ echo `ls` anaconda-ks.cfginstall.loginstall.log.syslog sh test testfile #只有用反引号包括命令,这个命令才会执行 [root@localhost ~]$ echo $(date) 2018年10月21日星期一18:25:09 CST #使用$(命令)的方式也是可以的
2. 变量的分类:
- 用户自定义变量: 这种变量是最常见的变量,由用户自由定义变量名和变量的值。
- 环境变量: 这种变量中主要保存的是和系统操作环境相关的数据,比如当前登录用户,用户的家目录,命令的提示符等。不是太好理解吧,那么大家还记得在Windows中,同一台电脑可以有多个用户登录,而且每个用户都可以定义自己的桌面样式和分辨率,这些其实就是Windows的操作环境,可以当做是Windows的环境变量来理解。环境变量的变量名可以自由定义,但是一般对系统起作用的环境变量的变量名是系统预先设定好的。
- 位置参数变量: 这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
- 预定义变量: 是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
变量分类 | 名称 | 作用 | 内容 |
---|---|---|---|
用户自定义变量 | 自定义 | 自定义 | 自定义 |
用户自定义环境变量 | 自定义 | 自定义 | 自定义 |
系统自带环境变量(/etc/profile) | 确定 | 确定 | 自定义 |
位置参数变量 | 确定 | 自定义 | 自定义 |
预定义变量 | 确定 | 自定义 | 自定义 |
2.1 用户自定义变量:
2.1.1 变量定义
[root@localhost ~]$ 2name="shen chao" -bash: 2name=shen chao: command not found #变量名不能用数字开头 [root@localhost ~]$ name = "shenchao" -bash: name: command not found #等号左右两侧不能有空格 [root@localhost ~]$ name=shen chao -bash: chao: command not found #变量的值如果有空格,必须用引号包含
2.1.2 变量调用
[root@localhost ~]$ name="shen chao" #定义变量name [root@localhost ~]$ echo $name #调用变量使用 $变量名 shen chao #输出变量name的值
2.1.3 变量查看
[root@localhost ~]$ set [选项] 选项: -u:如果设定此选项,调用未声明变量时会报错(默认无任何提示) -x:如果设定此选项,在命令执行之前,会把命令先输出一次 +<参数> :取消某个set曾启动的参数。 [root@localhost ~]$ set BASH=/bin/bash …省略部分输出… name='shen chao' #直接使用set 命令,会查询系统中所有的变量,包含用户自定义变量和环境变量 [root@localhost ~]$ set -u [root@localhost ~]$ echo $file -bash: file: unbound variable #当设置了-u选项后,如果调用没有设定的变量会有报错。默认是没有任何输出的。 [root@localhost ~]$ set -x [root@localhost ~]$ ls +ls --color=auto anaconda-ks.cfginstall.loginstall.log.syslog sh tdir testtestfile #如果设定了-x选项,会在每个命令执行之前,先把命令输出一次 [root@localhost ~]$ set +x #取消启动的x参数
2.1.4 变量删除
[root@localhost ~]$ unset 变量名
2.2 环境变量:
2.2.1 环境变量设置
[root@localhost ~]$ export age="18" #使用export声明的变量即是环境变量
2.2.2 环境变量查询和删除
env命令和set命令的区别:
set命令可以查看所有变量,而env命令只能查看环境变量。
[root@localhost ~]$ unset gender #删除环境变量gender [root@localhost ~]$ env | grep gender
2.2.3 系统默认环境变量
[root@localhost ~]$ env HOSTNAME=localhost.localdomain #主机名 SHELL=/bin/bash #当前的shell TERM=linux #终端环境 HISTSIZE=1000 #历史命令条数 SSH_CLIENT=192.168.4. 22 #当前操作环境是用ssh连接的,这里记录客户端ip SSH_TTY=/dev/pts/1 #ssh连接的终端时pts/1 USER=root #当前登录的用户 ..........更多参数可以使用set和env命令查看.............
2.3 位置参数变量:
位置参数变量 | 作用 |
---|---|
$n | n为数字,$0表示当前 Shell 脚本程序的名称,$1- |
9
代
表
第
一
到
第
九
个
参
数
,
十
以
上
的
参
数
需
要
用
大
括
号
包
含
,
如
9代表第一到第九个参数,十以上的参数需要用大括号包含,如
$1 是你给你写的shell脚本传的第一个参数,$2 是你给你写的shell脚本传的第二个参数…
[root@localhost sh]$ vim test.sh #!/bin/sh echo "shell脚本本身的名字: $0" echo "传给shell的第一个参数: $1" echo "传给shell的第二个参数: $2"
保存退出后,你在Test.sh所在的目录下输入 bash Test.sh 1 2
结果输出:
shell脚本本身的名字: Test.sh 传给shell的第一个参数: 1 传给shell的第二个参数: 2
KaTeX parse error: Undefined control sequence: \* at position 1: \̲*̲会把接收的所有参数当成一个整体…@则会区分对待接收到的所有参数。举个例子:
[root@localhost sh]$ vi parameter2.sh #!/bin/bash for i in"$\*" #定义for循环,in后面有几个值,for会循环多少次,注意“$\*”要用双引号括起来 #每次循环会把in后面的值赋予变量i #Shell把$\*中的所有参数看成是一个整体,所以这个for循环只会循环一次 do echo "The parameters is: $i" #打印变量$i的值 done x=1 #定义变量x的值为1 for y in"$@" #同样in后面的有几个值,for循环几次,每次都把值赋予变量y #可是Shel1中把“$@”中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次 do echo "The parameter$x is: $y" #输出变量y的值 x=$(( $x +1 )) #然变量x每次循环都加1,为了输出时看的更清楚 done
2.4 预定义变量:
预定义变量 | 作用 |
---|---|
$? | 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非О(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。 |
$$ | 当前进程的进程号(PID) |
$! | 后台运行的最后一个进程的进程号(PID) |
先来看看”$?”这个变量,举个例子说明
[root@localhost sh]$ ls count.sh hello.sh parameter2.sh parameter.sh #ls命令正确执行 [root@localhost sh]$ echo $? #预定义变量“$?”的值是0,证明上一个命令执行正确 [root@localhost sh]$ ls install.log ls:无法访问install.log:没有那个文件或目录 #当前目录中没有install.log文件,所以ls命令报错了 [root@localhost sh]$ echo $? 2 #变量“$?”返回一个非О的值,证明上一个命令没有正确执行 #至于错误的返回值到底是多少,是在编写ls命令时定义好的,如果碰到文件不存在就返回数值2
再来说明下”$ ”和” ”和” ”和”!”这两个预定义变量
[root@localhost sh]$ vi variable.sh #!/bin/bash echo "The current process is $$" #输出当前进程的PID. #这个PID就是variable.sh这个脚本执行时,生成的进程的PID find /root -name hello.sh & #使用find命令在root目录下查找hello.sh文件 #符号&的意思是把命令放入后台执行,工作管理我们在系统管理章节会详细介绍 echo "The last one Daemon process is $!" #输出这个后台执行命令的进程的PID,也就是输出find命令的PID号
3. 只读变量:
[root@localhost sh]$ vi readonly.sh #!/bin/bash a=10 #语法:readonly 变量名 readonly a a=20 #会报错readonly variable echo $a
4. 接受键盘输入:
[root@localhost ~]$ read [选项][变量名] 选项: -a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。 -p: “提示信息”:在等待read输入时,输出提示信息 -t: 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间 -n: 数字:read命令只接受指定的字符数,就会执行 -s: 隐藏输入的数据,适用于机密信息的输入 -d: 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。 -e: 在输入的时候可以使用命令补全功能。 变量名: 变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY. 如果只提供了一个变量名,则整个输入行赋予该变量. 如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有字
写个例子来解释下read命令:
[root@localhost sh]$ vi read.sh #!/bin/bash read -t 30 -p "Please input your name: " name #提示“请输入姓名”并等待30 秒,把用户的输入保存入变量name 中 echo "Name is $name" #看看变量“$name”中是否保存了你的输入 read -s -t 30 -p "Please enter your age: " age #提示“请输入年龄”并等待30秒,把用户的输入保存入变量age中 #年龄是隐私,所以我们用“-s”选项隐藏输入 echo -e "\n" #调整输出格式,如果不输出换行,一会的年龄输出不会换行 echo "Age is $age" read -n 1 -t 30 -p "Please select your gender[M/F]:" gender #提示“请选择性别”并等待30秒,把用户的输入保存入变量gender #使用“-n1”选项只接收一个输入字符就会执行(都不用输入回车) echo -e "\n" echo "Sex is $gender"
四、shell 运算符
在shell中,运算符和其他编程脚本语言一样,常见的有算数运算符、关系运算符、逻辑运算符、字符串运算符、文件测试运算符等
1. 算数运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 ` 而不是单引号 ‘):
[root@localhost ~]$ vi computer.sh #!/bin/bash val=`expr 2 + 2` echo "两数之和为 : $val" #注意 #表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。 #完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20
运算符 | 说明 | 举例 |
---|
- |加法 |
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。
注意:条件表达式要放在方括号之间,并且要有空格,必须写成 [ $a == $b ]。
[root@localhost ~]$ vi computers.sh #!/bin/bash a=10 b=20 echo ' ' echo 'a+b= ' `expr $a + $b` echo 'a-b= ' `expr $a - $b` echo 'a\*b= ' `expr $a \\* $b` echo 'a/b= ' `expr $a / $b` echo 'a%b= ' `expr $a % $b` #判断是否相等 if [ $a == $b ] then echo 'a等于b' else echo 'a不等于b' fi
2. 关系运算符
运算符 | 单词 | 说明 | 举例 |
---|---|---|---|
-eq | equal | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | not equal | 检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | great than | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | less than | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | great than or equal | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | less than or equal | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
[root@localhost ~]$ [ 10 -gt 10 ] [root@localhost ~]$ echo $? 1 [root@localhost ~]$ [ 10 -eq 10 ] [root@localhost ~]$ echo $? 0
案例:判断当前输入的用户是否存在。如果存在则提示“用户存在”否则提示“用户不存在”。
如果要在shell脚本使用linux命令,可以使用$()
包裹命令
例如:disk_size=$(df -h | awk ‘NR==2 {print $5}’)
[root@localhost ~]$ vim demo.sh #!/bin/bash #接受用户的输入 read -p '请输入需要查询的用户名:' username #获取指定用户名在passwd文件中出现的次数 count=$(cat /etc/passwd | grep $username | wc -l) #count=`cat /etc/passwd | grep $username | wc -l` #判断出现的次数,如果次数=0则用户不存在,反之存在 if [ $count == 0 ] then echo '用户不存在' else echo '用户存在' fi
3. 逻辑运算符
下表列出了常用的布尔运算符,假定变量 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。 |
或运算:一个为真即为真,全部为假才是假
与运算:一个为假即为假,全部为真才是真
4. 字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否为0,不为0返回 true。 | [ -n $a ] 返回 true。 |
str | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
5. 文件测试运算符(重点)
文件测试运算符用于检测 Unix/Linux 文件的各种属性。
操作符 | 说明 | 举例 |
---|---|---|
-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 $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
注意:权限几个判断,如果只有一个部分符合,则认为是有权限的。
五、流程控制
1. if条件判断
1.1 单分支if条件
语法:
if [ 条件判断式 ] then 程序 fi
案例:统计根分区使用率
[root@localhost ~]$ vi sh/if1.sh #!/bin/bash #统计根分区使用率 rate=$(df -h | grep "/dev/sda2" | awk '{print $5}’| cut -d "%"-f1) #把根分区使用率作为变量值赋予变量rate if [ $rate -ge 80 ] #判断rate的值如果大于等于80,则执行then程序 then echo "Warning!/dev/sda3 is fu11!!" #打印警告信息。在实际工作中,也可以向管理员发送邮件。 fi
案例:创建目录
[root@localhost ~]$ vi sh/add_dir.sh #!/bin/bash #创建目录,判断是否存在,存在就结束,反之创建 echo "当前脚本名称为$0" DIR="/media/cdrom" if [ ! -e $DIR ] then mkdir -p $DIR fi echo "$DIR 创建成功"
1.2 双分支if条件语句
语法:
if [ 条件判断式 ] then 条件成立时,执行的程序 else 条件不成立时,执行的另一个程序 fi
案例1:备份mysql数据库
[root@localhost ~]$ vi sh/bakmysql.sh #!/bin/bash #备份mysql数据库。 ntpdate asia.pool.ntp.org &>/dev/null #同步系统时间 date=$(date +%y%m%d) #把当前系统时间按照“年月日”格式赋子变量date size=$(du -sh/var/lib/mysql) #统计mysql数据库的大小,并把大小赋予size变量 if [ -d /tmp/dbbak ] #判断备份目录是否存在,是否为目录 then #如果判断为真,执行以下脚本 echo "Date : $date!" > /tmp/dbbak/dbinfo.txt #把当前日期写入临时文件 echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt #把数据库大小写入临时文件 cd/tmp/dbbak #进入备份目录 tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &> /dev/null #打包压缩数据库与临时文件,把所有输出丢入垃圾箱(不想看到任何输出) rm -rf /tmp/dbbak/dbinfo.txt #删除临时文件 else mkdir /tmp/dbbak #如果判断为假,则建立备份目录 echo "Date : $date!" > /tmp/dbbak/dbinfo.txt echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt #把日期和数据库大小保存如临时文件 cd /tmp/dbbak tar -zcf mysql-lib-$date.tar. gz dbinfo.txt /var/lib/mysql &> /dev/null #压缩备份数据库与临时文件 rm -rf/tmp/dbbak/dbinfo.txt #删除临时文件 fi
案例2:判断apache是否启动,如果没有启动则自动启动
[root@localhost ~]$ vi sh/autostart.sh #!/bin/bash #判断apache是否启动,如果没有启动则自动启动 port=$(nmap -sT 192.168.4.210 | grep tcp | grep http | awk '{print $2}’) #使用nmap命令扫描服务器,并截取 apache服务的状态,赋予变量port #只要状态是open,就证明正常启动 if [ "$port" == "open"] #如果变量port的值是“open” then echo "$(date) httpd is ok!” >> /tmp/autostart-acc.log #则证明apache 正常启动,在正常日志中写入一句话即可 else /etc/rc.d/init.d/httpd start &>/dev/null #否则证明apache没有启动,自动启动apache echo "$(date) restart httpd !!" >> /tmp/autostart-err.log #并在错误日志中记录自动启动apche 的时间 fi
nmap端口扫描命令,格式如下:
[root@localhost ~]$ nmap -sT 域名或IP 选项: -s 扫描 -T 扫描所有开启的TCP端口 #知道了nmap命令的用法,我们在脚本中使用的命令就是为了截取http的状态,只要状态是“or. #就证明apache启动正常,否则证明apache启动错误。来看看脚本中命令的结果: [root@localhost ~]$ nmap -sT 192.168.4.210 | grep tcp | grep http | awk ' fprint $2}’ #扫描指定计算机,提取包含tcp 的行,在提取包含httpd 的行,截取第二列open #把截取的值赋予变量port
1.3 多分支if条件语句
语法:
if [ 条件判断式1 ] then 当条件判断式1成立时,执行程序1 elif [ 条件判断式2 ] then 当条件判断式2成立时,执行程序2 …省略更多条件… else 当所有条件都不成立时,最后执行此程序 fi
案例:判断用户输入的是什么文件
[root@localhost ~]$ vi sh/if-elif.sh #!/bin/bash #判断用户输入的是什么文件 read -p "Please input a filename: " file #接收键盘的输入,并赋予变量file if [ -z "$file” ] #判断file变量是否为空 then echo "Error, please input a filename" #如果为空,执行程序1,也就是输出报错信息 exit 1 #退出程序,并返回值为Ⅰ(把返回值赋予变量$P) elif [ ! -e "$file” ] #判断file的值是否存在 then echo "Your input is not a file!" #如1果不存在,则执行程序2 exit 2 #退出程序,把并定义返回值为2 elif [ -f "$file” ] #判断file的值是否为普通文件 then echo "$file is a regulare file!” #如果是普通文件,则执行程序3 elif [ -d "$file” ] #到断file的值是否为目录文件 then echo "$file is a directory!" #如果是目录文件,网执行程序4 else echo "$file is an other file!” #如果以上判断都不是,则执行程序5 fi
2. 多分支case条件语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
case语句语法如下:
case $变量名 in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 :: …省略其他分支… \*) 如果变量的值都不是以上的值,则执行此程序 ;; esac
这个语句需要注意以下内容:
- case语句,会取出变量中的值,然后与语句体中的值逐一比较。如果数值符合,则执行对应的程序,如果数值不符,则依次比较下一个值。如果所有的值都不符合,则执行 “*)” (*代表所有其他值)中的程序。
- case语句以“case”开头,以“esac”结尾。
每一个分支程序之后要通过“;;”双分号结尾,代表该程序段结束(千万不要忘记,每次写case语句,都不要忘记双分号)。
案例:
[root@localhost ~]$ vi sh/if-case.sh #!/bin/bash read -p "请输入一个字符,并按Enter确认:" KEY case "$KEY" in [a-z]|[A-Z]) echo "您输入的是字母" ;; [0-9]) echo "您输入的是数字" ;; \*) echo "您输入的是其他字符" ;; esac
3. for循环
for循环是固定循环,也就是在循环时已经知道需要进行几次的循环,有时也把for循环称为计数循环。for的语法有如下两种:
语法一:
for 变量 in 值1 值2 值3 …(可以是一个文件等) do 程序 done 这种语法中for循环的次数,取决于in后面值的个数(空格分隔),有几个值就循环几次,并且每次循环都把值赋予变量。 也就是说,假设in后面有三个值,for会循环三次,第一次循环会把值1赋予变量,第二次循环会把值2赋予变量,以此类推。
语法二:
for (( 初始值;循环控制条件;变量变化 )) do 程序 done 语法二中需要注意: 初始值:在循环开始时,需要给某个变量赋予初始值,如i=1; 循环控制条件:用于指定变量循环的次数,如i<=100,则只要i的值小于等于100,循环就会继续; 变量变化:每次循环之后,变量该如何变化,如i=i+1。代表每次循环之后,变量i的值都加1。
语法一举例:打印时间
[root@localhost ~]$ vi sh/for.sh #!/bin/bash #打印时间 for time in morning noon afternoon evening do echo "This time is $time!" done
语法一举例:批量解压缩脚本
[root@localhost ~]$ vi sh/auto-tar. sh #!/bin/bash #批量解压缩脚本 cd/lamp #进入压缩包目录 ls \*.tar.gz > ls.log #把所有.tar.gz结尾的文件的文件覆盖到ls.log 临时文件中 for i in $(cat ls.log) ` #或者这样写for i in `cat ls.log` #读取ls.log文件的内容,文件中有多少个值,就会循环多少次,每次循环把文件名赋予变量i do tar -zxf $i &>/dev/null #加压缩,并把所有输出都丢弃 done rm -rf /lamp/ls.log #删除临时文件ls.log
语法二举例:从1加到100
[root@localhost ~]$ vi sh/add. sh #!/bin/bash #从1加到100 s=0 for (( i=1;i<=100;i=i+1 )) #定义循环100 次 do s=$(( $s+$i )) #每次循环给变量s赋值 done echo "The sum of 1+2+...+100 is : $s" #输出1加到100的和
语法二举例:批量添加指定数量的用户
[root@localhost ~]$ vi useradd.sh #!/bin/bash #批量添加指定数量的用户 read -p "Please input user name: " -t 30 name #让用户输入用户名,把输入保存入变量name read -p "Please input the number of users: " -t 30 num #让用户输入添加用户的数量,把输入保存入变量num read -p "Please input the password of users: " -t 30 pass #让用户输入初始密码,把输入保存如变量pass if [ ! -z "$name" -a ! -z "$num"-a ! -z "$pass"] #判断三个变量不为空 then y=$(echo $num | sed 's/[0-9]//g') #定义变量的值为后续命令的结果 #后续命令作用是,把变量num 的值替换为空。如果能替换为空,证明num 的值为数字 #如果不能替换为空,证明num的值为非数字。我们使用这种方法判断变量num 的值为数字 if [ -z "$y"] #如果变量y的值为空,证明num变量是数字 then for (( i=1 ; i<=$num; i=i+1 )) #循环num变量指定的次数 do /usr/sbin/useradd $name$i &>/dev/null #添加用户,用户名为变量name 的值加变量i的数字 echo $pass | /usr/bin/passwd --stdin $name$i &>/dev/null #给用户设定初始密码为变量pass 的值 done fi fi
语法二举例:批量删除用户
[root@localhost ~]$ vi sh/userdel.sh #!/bin/bash #批量删除用户 user=$(cat /etc/passwd | grep " /bin/bash"|grep -v "root"Icut -d ":" -f 1) #读取用户信息文件,提取可以登录用户,取消root用户,截取第一列用户名 for i in $user #循环,有多少个普通用户,循环多少次 do userdel -r $i #每次循环,删除指定普通用户 done
4. while循环
对while循环来讲,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。
语法:
while [ 条件判断式 ] do 程序 done
案例:1加到100
[root@localhost ~]$ vi sh/addnum.sh #!/bin/bash #从1加到100 i=1 s=0 #给变量i和变量s赋值 while [ $i -le 100 ] #如果变量i的值小于等于100,则执行循环 do s=$(( $s+$i )) i=$(( $i+1 )) done echo "The sum is: $s"
案例:输入的数值进行比较判断
[root@localhost ~]$ vi sh/addnum.sh #!/bin/bash PRICE=$(expr $RANDOM % 1000) TIMES=0 echo "商品的价格为0-999之间,猜猜看是多少?" while true do read -p "请输入您猜的价格:" INT let TIMES++ if [ $INT -eq $PRICE ] ; then echo "恭喜您猜对了,实际价格是 $PRICE" echo "您总共猜了 $TIMES 次" exit 0 elif [ $INT -gt $PRICE ] ; then echo "太高了" else echo "太低了" fi done
5. until循环
和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
语法:
until [ 条件判断式 ] do 程序 done
案例一:1加到100
[root@localhost ~]$ vi sh/until.sh #!/bin/bash #从1加到100 i=1 s=0 #t给变量i和变量s赋值 until [ $i -gt 100 ] #循环直到变量i的值大于100,就停止循环 do s=$(( $s+$i )) i=$(( $i+1 )) done echo "The sum is: $s"
6. 函数
语法:
function 函数名 () { 程序 }
案例:接收用户输入的数字,然后从1加到这个数字
[root@localhost ~]$ vi sh/function.sh #!/bin/bash #接收用户输入的数字,然后从1加到这个数字 function sum () { #定义函数sum s=0 for (( i=0; i<=$num;i=i+1 )) #循环直到i大于$1为止。$1是函数sum 的第一个参数 #在函数中也可以使用位置参数变量,不过这里的$1指的是函数的第一个参数 do s=$(( $i+$s )) done echo "The sum of 1+2+3...+$1 is :$s" #输出1加到$1的和 } read -p "Please input a number: " -t 30 num #接收用户输入的数字,并把值赋予变量num y=$(echo $num | sed 's/[0-9]//g') #把变量num的值替换为空,并赋予变量y if [ -z "$y"] #判断变量y是否为空,以确定变量num中是否为数字 then sum $num #调用sum函数,并把变量num的值作为第一个参数传递给sum函数 else echo "Error!! Please input a number!" #如果变量num 的值不是数字,则输出报错信息 fi
7. 特殊流程控制语句
7.1 exit语句
系统是有exit命令的,用于退出当前用户的登录状态。可是在Shell脚本中,exit语句是用来退出当前脚本的。也就是说,在Shell脚本中,只要碰到了exit语句,后续的程序就不再执行,而直接退出脚本。
exit的语法如下:
exit [返回值]
如果exit命令之后定义了返回值,那么这个脚本执行之后的返回值就是我们自己定义的返回值。可以通过查询$?这个变量,来查看返回值。如果exit之后没有定义返回值,脚本执行之后的返回值是执行exit 语句之前,最后执行的一条命令的返回值。写一个exit 的例子:
[root@localhost ~]$ vi sh/exit.sh #!/bin/bash #演示exit的作用 read -p "Please input a number: " -t 30 num #接收用户的输入,并把输入赋予变量num y=$ (echo $num | sed 's/[0-9]//g') #如果变量num 的值是数字,则把num的值替换为空,否则不替换 #把替换之后的值赋予变量y [ -n "$y" ] && echo "Error! Please input a number!" && exit 18 #判断变量y的值如果不为空,输出报错信息,退出脚本,退出返回值为18 echo "The number is: $num" #如果没有退出加班,则打印变量num中的数字
7.2 break语句
当程序执行到break语句时,会结束整个当前循环。而continue 语句也是结束循环的语句,不过continue 语句单次当前循环,而下次循环会继续。
先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
需要这份系统化的资料的朋友,可以点击这里获取!
+ 1 i s : 1 is : 1is:s”
#输出1加到$1的和
}
7. 特殊流程控制语句 7.1 exit语句 系统是有exit命令的,用于退出当前用户的登录状态。可是在Shell脚本中,exit语句是用来退出当前脚本的。也就是说,在Shell脚本中,只要碰到了exit语句,后续的程序就不再执行,而直接退出脚本。 exit的语法如下:
exit [返回值]
如果exit命令之后定义了返回值,那么这个脚本执行之后的返回值就是我们自己定义的返回值。可以通过查询$?这个变量,来查看返回值。如果exit之后没有定义返回值,脚本执行之后的返回值是执行exit 语句之前,最后执行的一条命令的返回值。写一个exit 的例子:
7.2 break语句 当程序执行到break语句时,会结束整个当前循环。而continue 语句也是结束循环的语句,不过continue 语句单次当前循环,而下次循环会继续。 先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。 [外链图片转存中...(img-G5xRfMtg-46)] [外链图片转存中...(img-ANkBQ6IF-47)] [外链图片转存中...(img-A8PGHRaw-47)] [外链图片转存中...(img-xC46lfGE-47)] [外链图片转存中...(img-rFx5ecxn-48)] 既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化! 由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新 [需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132947.html