文章目录
Shell编程规范与变量
Shell脚本概述
Shell脚本的概念
- 将要执行的命令按顺序保存到一个文本文件
- 给该文件可执行权限
- 可结合各种Shell控制语句以完成更复杂的操作
Shell脚本应用场景
- 重复性操作
- 交互性任务
- 批量事务处理
- 服务运行状态监控
- 定时任务执行
- ……
Shell的作用
- 命令解释器,“翻译官”
- 介于系统内核与用户之间,负责解释命令行
- 系统上合法的Shell要写入/etc/shells,系统某些服务运行过程中,会去检查用户能够使用的Shell,而这些Shell的查询借助于/shell/shells文件
- 用户登录时,系统会给一个Shell来给用户使用,而这个登陆取得的Shell就记录在/etc/passwd中。
用户登陆的Shell
-
登陆后默认使用的Shell程序,一般为/bin/bash
-
不同的Shell的内部指令、运行环境等会有所区别
-
Linux中的shell
-
检查一下/etc/shells这个文件,里面就是Linux所包含的Shell。
-
最常用的就是bash、tcsh、csh、sh、nologin这些shell。这些shell都是依据Linux发展者的不同所创造出的不同版本。
-
bash:基准于GNU的框架下发展出的Shell。
-
csh:语法有点类似于c语言的Shell。
-
tcsh:整合了csh,提供更多的功能。sh:已经被bash所替换。
-
nologin:这个shell可以让用户无法登录主机。
-
shell脚本的作用
-
自动化运维
-
批量化重复操作可以编写脚本结合计划任务自动周期运行
-
减轻管理员工作量
-
提高处理文本文件的速度避免配置出错
Shell是一个面向字符串的编程语言,可以跟Python之类的其他语言配合起来,比如某个复杂的功能使用一个Python脚本来实现,然后在shell中调用这个脚本实现较复杂的功能;或者反过来,在Python脚本中调用外部的Shell脚本来提高自动化的效率,也是可以的。
Shell编程规范
-
Shell脚本的构成
- 脚本申明(解释器)∶若第一行为"#!/bin/bash",表示此行以下的代码语句是通过/bin/bash程序来解释执行,#/bin/bash为默认解释器。还有其它类型的解释器,比如#!/usr/bin/python、#!/usr/bin/expect。
- 注释信息:以"#"开头的语句表示为注释信息,被注释的语句在运行脚本时不会被执行。
- 可执行语句:比如echo命令,用于输出" "之间的字符串
-
编写脚本代码
-
使用vim文本编辑器
vim /root/first.sh
每行一条Linux命令,按执行顺序依次编写
#!/bin/bash #This is my first shell-script. cd /boot echo "当前的目录位于:"pwd echo "其中以vml开头的文件包括:"ls -lh vml*
-
赋予可执行权限,使脚本具有可执行属性
chmod +x first.sh
-
Shell脚本的执行
-
方法一:指定路径的命令,要求文件必须有x权限。(执行在脚本中的shell环境)
chmod +x /root/first.sh
- 指定绝对路径:
/root/first.sh
- 指定相对路径:
./first.sh
- 指定绝对路径:
-
方法二:指定shell来解释脚本,不要求文件必须有x权限。(执行在当前用户所在的shell环境)
-
sh脚本路径:
sh first.sh
-
source脚本路径:
. first.sh
或者source first.sh
-
-
重定向与管道
管道操作 “|”
-
将管道符号"|"左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。
ps aux l wc -l
echo "abc123" | passwd --stdin zhangsan
交互式硬件设备
-
标准输入:从该设备接收用户输入的数据
-
标准输出:通过该设备向用户输出数据
-
标准错误:通过该设备报告执行出错信息
类型 设备文件 文件描述编号 默认设备 标准输入 /dev/stdin 0 键盘 标准输出 /dev/stdout 1 显示器 标准错误输出 /dev/stderr 2 显示器
重定向操作
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < | 从指定的文件读取数据,而不是从键盘输入 |
重定向输出 | > | 将输出结果保存到指定的文件(覆盖原有内容) |
重定向输出 | >> | 将输出结果追加到指定的文件尾部 |
标准错误输出 | 2> | 将错误信息保存到指定的文件(覆盖原有内容) |
标准错误输出 | 2>> | 将错误信息追加到指定的文件中 |
混合输出 | &> | 将标准输出、标准错误的内容保存到同一个文件中 |
混合输出 | 2>&1 | 将标准输出、标准错误的内容保存到同一个文件中 |
-
ls -lh > log.txt 2>&1
等同于ls -lh &> log.txt
-
本来1–>屏幕(1指向屏幕)
-
执行>log后,1–>log.txt(1指向log.txt)
-
执行2>&1后,2–>1(2指向1,而1指向log.txt,因此2也指向了log.txt)
-
-
echo "123456" > pass.txt
passwd --stdin zhangsan < pass.txt
从pass.txt文件中取密码,需要注意SELinux会影响此命令执行,若执行失败可尝试关闭SELinux
Shell脚本变量
Shell变量的作用、类型
-
变量的作用
-
用来存放系统和用户需要使用的特定参数(值)
变量名:使用固定的名称,由系统预设或用户定义
变量值:能够根据用户设置、系统环境的变化而变化
-
-
变量的类型
- 自定义变量:由用户自己定义、修改和使用
- 特殊变量
- 环境变量:由系统维护,用于设置工作环境
- 只读变量:不能被修改
- 位置变量:通过命令行给脚本程序传递参数
- 预定义变量:Bash中内置的一类变量,不能直接修改
自定义变量
/etc/profile中可设置重启不消失的变量(export全局)
-
定义一个新的变量
-
变量名以字母或下划线开头,区分大小写,建议全大写
变量名=变量值 //变量值包含空格或者其他特殊符号时,要用引号包裹
-
declare
declare [+/-][rxi][变量名称=设置值] 或 declare -f
- +/-:"-“指定变量的属性,”+"是取消变量所设的属性。
- -f :仅显示函数。
- -r:将变量设置为只读。
- -x :指定的变量会成为环境变量,可供shell以外的程序来使用。
- -i :[设置值]可以是数值,字符串或运算式。
-
-
-
查看变量的值
echo $变量名 //要在变量名后添加其他字符时,需要用{}将变量分隔出来,防止产生歧义
-
赋值时使用引号
- 双引号:允许通过$符号引用其他变量值
- 单引号:禁止引用其他变量值,$视为普通字符
- 反撇号:命令替换,提取命令执行后的输出结果(相当于"$(……)")
-
从键盘输入内容为变量赋值
read [-p "提示信息"] 变量名
echo -n "……" //不换行输出,默认情况下输出结束即换行
-
变量作用范围
-
默认情况下,新定义的变量只在当前的Shell环境中有效,因此称为局部变量。当进入子程序或新的子Shell环境时,局部变量将无法再使用。
-
可以通过内部命令export将指定的变量导出为全局变量,使用户定义的变量在所有的子Shell环境中能够继续使用
- 格式1:
export 变量名
- 格式2:
export 变量名=变量值
- 格式1:
-
可以使用pstree命令查看shell环境
-
输入bash命令进入子shell环境,
-
按Ctrl+D组合键或输入exit命令退出子shell环境
export product version #导出为全局变量 bash echo " $product $version" #子程序引用全局变量
整数变量的运算
-
整数变量的运算
expr 变量1 运算符 变量2 [运算符变量3] …… //注意空格
-
常用运算符
- 加法运算:+
- 减法运算:-
- 乘法运算:
\*
- 除法运算:/(得到商)
- 求模(取余)运算:%
[ ] 和 [ ]和 []和(( ))括号中可以整数变量运算也不一定必须加空格
let i=12*5:let可以整数变量运算
-
常用的运算表达式
i=$(expr 12 \* 5)
i=$((12 * 5))
i=$[12 * 5]
let i=12\*5
在ksh中的test
数字的运算可使用let、(()),其中运算时不需要变量$符号,运算符为+、-、
*
、/、%,不建议使用expr数字的比较使用(()),其运算符>、>=、<、<=、==、!=
可以使用算术扩展,如:
(( 99+1 <= 101 ))
字符表达式的比较使用[[ ]],其运算符=、!=、-n、-Z
文件表达式的测试使用[[ ]],其运算符-r、-l、-w、-x、-f、-d、-s、-nt、-ot
逻辑表达式的测试使用[[ ]],其运算符!、&&、ll
数字比较、字符比较、逻辑测试可以组合,如
$[[ "a" != "b" && 4 -gt 3 ]]
支持bash中的通配符扩展,如:
[[ hest = h??t ]]
、[ hest = h*t ]]
使用(())时,不需要空格分隔各值和运算符,使用[[]]时需要用空格分隔各值和运算符。
bash与ksh中的[[]]不同
- 在redhat9的bash中也可以使用[[]]符号。但是建议严格按照上面的原则使用。
- 在bash中,数字的比较最好使用(()),虽说可以使用[[]],但若在其内使用运算符>、>=、<、<=、==, !=时,其结果经常是错误的,不过若在[[ ]]中使用[ ]中的运算符"-eq、-ne、-le、-lt、-gt、-ge”等,还尚未发现有错。因此诸如$[[ “a” != “b” && 4>3 ]]这类组合(见上)也不可以在bash中使用,其出错率很高。
- 例:
[[ "a" != "b" && 10 > 2]]
判断结果就不正常。- 诸如
[ 2 \< 10 ]
、[[ 2 < 10 ]]
都是不要使用。使用算术扩展最好用(( 99+1 == 100 )),而不要使用[[ 99+1 -eq 100 ]]。
浮点运算
-
bash不支持浮点运算,如果需要进行浮点运算,需要借助bc, awk处理。
#!/ bin/bash # 加 f=$(echo "4.3+2.5" | bc) echo " 4.3+2.5=$f" #减 f=$(echo "4.3-2.5" | bc) echo "4.3-2.5=$f" #乘 f=$(echo "4.30*2.50" | bc) echo "4.3*2.5=$f" #除 f=$(echo "scale=2;4.3/2.5" | bc) # scale指定保留小数位数 echo "4.3/2.5=$f" #混合运算 f=$(echo "5.6/(2.2-1.1)*2+1.1" | bc) echo "5.6/(2.2-1.1)*2+1.1=$f" # --------------------- #加 f=$(awk 'BEGIN{print 4.5+3.4} ') # BEGIN最多六位小数 echo "4.5+3.4=$f" #减 f=$(awk 'BEGIN{print 4.5-3.4} ') echo "4.5-3.4=$f" #乘 f=$(awk 'BEGIN{print 4.5*3.4}') echo "4.5*3.4=$f" #除 f=$(awk 'BEGIN{print 4.5/3.4}') echo "4.5/3.4=$f" #混合 f=$(awk 'BEGIN{print (4.5-3.4)*2+3} ') echo " (4.5-3.4)*2+3=$f"
特殊的Shell变量
-
环境变量
-
由系统提前创建,用来设置用户的工作环境
-
配置文件: /etc/profile、~/.bash_profile
-
常见的环境变量(env 显示当前环境变量)
-
PWD、PATH
-
USER、SHELL、HOME
-
-
-
只读变量
- 用于变量值不允许被修改的情况,不可改变、删除、unset(重启可以消除)
- 定义格式:
readonly name=xxx
declare -r name=xxx
:declare定义只读变量
-
位置变量
-
表示为$n,n为1~9之间的数字
-
vim num.sh
#!/bin/bash echo $1 echo $2 echo $3 echo $4 echo $5 echo $6 echo $7 echo $8 echo $9 echo ${10} #9以上的位置参数要用{}括起来,否则输出$1加0
./num.sh 1 2 3 4 5 6 7 8 9 10
-
vim cal.sh
#!/bin/bash num1=$1 #传入 num2=$2 sum=$[num1 + bum2] echo "$1 + $2 = $sum"
./cal.sh 10 20
-
位置变量可用于给脚本传参
-
-
预定义变量
-
$*
和$@
:表示命令或脚本要处理的参数。-
$*
:把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"$1 $2 $3 $4"。 -
$@
:把各个参数加上双引号分隔成n份的参数列表,每个参数作为一个字符串返回,代表"$1""$2"$3""$4"。 -
#!/bin/bash echo "未加双引号时,两者相同" echo $* echo $@ echo "加上引号后对比" for i in "$*" do echo $i echo "" done # 结果仅一次性输出所有参数 echo "----------" for j in "$@" do echo $i echo "" done # 结果依次输出所有参数
-
-
$0:表示当前执行的脚本或命令(进程/程序名)的名称。
-
$#:表示命令或脚本要处理的参数的个数。
-
$?:表示前一条命令或脚本执行后的返回状态码,返回值为0表示执行正确,返回任何非0值均表示执行出现异常(包括无结果产生的执行)。也常被用于 shell 脚本中 return 退出函数并返回的退出值。
vim mybak.sh
#!/bin/bash time=backup-`date +%F`.tgz # 指定归档文件名样式 tar zcf bak-${time}.tar.gz $* &> /dev/null #/dev/null表示的是一个黑洞文件,通常用于丢弃不需要的数据输出,这里丢弃任务完成过程中的提示 echo "已执行$0脚本进行文件备份" echo "共完成$#个对象的备份" echo "具体内容包括:$@。"
chmod +x mybak.sh
./mybak.sh /etc/passwd /etc/shadow /etc/yum.conf /etc/yum.repos.d/
-