入门与规范 shell脚本编写规范
脚本文件后缀名:本质上就是一个文本文件,建议保存为.sh
首行格式规范: #! /bin/bash 含义:声明shell解析器
注释格式
脚本文件的执行方式 1 2 3 4 5 6 7 8 # 新建子进程执行 sh helloworld.sh # 在原进程执行 source helloworld.sh # 注意:这种方式脚本文件需要有执行权限 ./helloworld.sh
变量 环境变量
linux系统加载Shell的配置文件中定义的变量共享给所有的Shell程序
环境变量所在的配置文件
全局配置文件(系统级环境变量)
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置文件(用户及环境变量)
当前用户/.basg_profile
当前用户/.bashrc
环境变量相关指令
查看当前Shell 环境变量:env
查看所有变量(系统环境变量+自定义变量+函数):set
自定义系统环境变量
编辑/etc/profile全局配置文件
添加环境变量:export var1=var
重载配置文件:source /ect/profile
环境变量加载流程原理 Shell工作环境
交互式与非交互式
登录与非登录
登录:正常用户需要登录才能使用linux系统
非登录:一些特殊的用户,不需要登录就可以进入linux系统的Shell环境
识别登录与非登录环境:$0
-bash Shell登录环境
bash Shell非登录环境
工作环境切换
用户切换时
登录:su -l root
非登录:su root
登录->非登录:bash
以工作化环境执行脚本:sh -l / bash -l
环境加载的过程
用户登录后,开始加载以下流程
自定义变量 自定义脚本内部全局变量
var_name=value
定义规则:
等号两侧不能有空格
变量的默认类型是字符串,无法直接进行数值运算
变量的值如果有空格,必须用双引号括起来
自定义常量:realonly
自定义局部常量:local
自定义环境变量
定于语法:export var_name=value
全局变量的定义:在父环境中定义,在子环境中也可以使用
父子Shell环境:在A.sh中执行B.sh,则A.sh为父Shell环境,即调用者为父
删除变量 unset var
使用变量 $a ${a:2}
${}
中{}
用以标识变量及其附属属性的一体性,主要作用于数组与子串以及map类型,其他时候$a与${a}
无异
字符串变量格式及其区别
单引号:可以转义,可以包含空格,无法解析的变量,但可以用子串与变量拼接构造大字符串,主要用于字符串中存在大量"
时(如json),用'
规避转义
双引号 :可以解析变量,可以转义,可以包含空格
无引号:不能包含空格,不能转义
字符串操作
获取长度:
拼接:"${var1}${var2}"
截取:
map类型变量 1 2 3 4 5 # 定义关联数组(map),关联数组只能用declare declare -A aMap=([key]=value [key1]=value2) echo ${aMap[key]} #获取值 aMap[key]=22 echo ${aMap[key]} #获取值
特殊符号变量
$n
:接收脚本文件入参
$1-$9,代表获取第一到第九的参数
第10个参数以上:${数字}
$0 用于获取脚本名称
参数传入语法:sh helloworld.sh param1 param2
$#
:获取输入参数的个数
$*
/$@
:都是获取所有输入参数并当成一个字符串
不使用双引号,功能是一样的
使用双引号
$*
输出的是一个整体
$@
输出"$1" "$2" "$3"
在循环时体现区别,$@可以for var in $@
,$* 不能
$?
:获取上一个Shell或者函数的返回值
每个Shell都有一个返回值,用以说明时候执行成功
一般来说,0表示成功,非0表示失败
$$$$:获取当前Shell系统的进程ID号
变量数组
注意:Bash Shell 只支持一维数组
数组的定义 1 2 3 # ()表示数组,空格来分隔 array1=(item1 item2 item3) #方式1 array2=(${array1[2]} ${array1[1]} ${array1[0]}) #方式2
数组的获取
数组拼接与删除 数组拼接 1 2 arr1=(${arr2[@]} ${arr3[@]}) arr1=(${arr2[*]} ${arr3[*]})
数组删除 1 2 unset arr[1] #删除元素 unset arr #删除整个数组
常用内置命令 含义
是Shell内部的命令,可以直接使用,与之对应的是外部脚本文件
两者(内置命令与外部脚本文件)的区别
内置命令:Shell进程的一部分(指令在内存),在进程内部执行
外部脚本文件:存储在磁盘上,运行需要fork新的进程运行
使用type
命令可以判断是内部还是外部
设置别名:alias 1 2 alias ls="ls -l" #设置别名,最常见的应用就是 ll unalias ll #删除别名
输出字符串:echo 1 2 echo -n "输出内容" #输出不换行的字符串 echo -e "hello\nworld" #-e 执行转义字符:\n:换行 \c:清除换行
读取控制台输入:read
简介:用于从标准输入中读取数据并给变量赋值,若标准输入重定向,这可以从文件中读取数据
1 read [-options] [var1 var2 ....] #基础表达式
options:
意味着Shell获取命令行数据时,可以实现以下功能:
读取数据
指定结束字符串
是否转义
读取指个数的字符 :read -n 1 var
设置提示信息 :read -p "请输入地址:" addr
拒绝转义
输入不重现 : read -p "请输入密码" pwd -s
设置输出超时时间 ,配合 #?
使用 : read -t 10 var #10内完成输入,否则失败
设文件为输入源
结束当前Shell环境进程:exit
exit 可以返回一个状态码,使用$?
可以获取状态码
1 2 exit #返回0,一般任务命令执行成功 exit 1 #数字的范围建议0-255
设置变量类型 :declare 1 2 3 4 5 6 7 8 9 10 11 12 # 设置变量的属性 # a:索引数组,A:关联数组(map), # r:只读,x:设置为环境变量, # i:整型变量,f:函数 declare [+/-][aArxif][变量名称=初始值] # 查看全部变量与函数 declare declare -f #所有函数定义 declare -F #所有函数名称列表 # 定义关联数组(map),关联数组只能用declare declare -A aMap=([key]=value [key1]=value2 ...) $ {aMap[key]}
运算表达式
总结:执行命令用$(),数值的计算(()),判断用[[]],复杂数学计算用bc
``与$():
嵌套执行时,``需要转义
$()比``可读性更强,推荐使用$()
expr命令:求值表达式 1 result=`expr 1 + 2` #这里使用的是反引号``,且只能进行整数运算,用操作符间要用空格隔开
let 1 2 3 # let 只能用于赋值let a=b+1 let a=b+1 b=c+1 #多个用空格隔开
$[] 1 2 # $[]表达式内部不用对变量赋值 b=$[a+1]
(()): 整数运算
(())内变量有无$均可
(())中会忽视空格
支持算数运算与关系运算
1 2 3 4 5 6 7 # 赋值 ((a=b+1)) a=$((b+1)) ((a=35+2,b=1+5)) # 多个表达式用,隔开 # 比较 (($ a<$b )) (($ a<$b &&$a <$c ))
test[]和[[]]:判断符:测试
[[或[之后,]]或]之前都需要空格
[]与[[]]支持的运算符
测试内容
[ ]
[[ ]]
数字测试
-eq(=,==),-ne(!=),-lt(\>),-le,-gt(\>) -ge,不支持=和<=
同[ ],<和>不需要转义
文件测试
-r,-l,-w,-x,-f,-d,-s,-nt,-ot等
同[ ]
字符测试
-eq(=,==),-ne(!=),-n -z
同[ ]
逻辑测试
-a,-o,!
**! ,\
\
,&&**
数字运算
不可以使用
+,-,*,/,%
1 2 3 4 [[ $a==$b ]] #字符串比较不支持,>=、<=,只能用这种方式表达 [[ -z $a ]] #字符串是否为空 [[ -n $a ]] #字符串是否不为空 [[ $a ]] #字符串是否不为空
文件测试运算符 1 2 3 4 5 6 7 8 9 [[ -d file ]] #是否是目录 [[ -f file ]] #是否是普通文件 [[ -r file ]] #是否可读 [[ -w file ]] #是否可写 [[ -x file ]] #是否可执行 [[ -s file ]] #是否为空 [[ -e file ]] #是否存在 [[ file1 -nt file2 ]] #file1是否比file2新 [[ file1 -ot file2 ]] #file1是否比file2旧
bc命令:linux的内置计算器
语法:bc [options] [参数]
使用内置函数:bc -l
显示告警信息:bc -w
不显示欢迎信息:bc -q
退出:quit
内置变量
scala:结果精度
ibase:输入的进制
obase:输出的进制
last或者.:获取最近打印的结果
内置函数
s(x):计算正弦值,x为数值,即Π=360°
c(x):计算余弦值
a(x):计算正反切
l(x):计算x的自然对数
e(x):计算e的x次方
j(n,x):计算n到x的阶数
互动式的数学运行
标准计算器的使用:即输入表达式,回车输出结果
也可以直接读取整个文件:bc file
,一次性把表达式全输入,结果全输出
非互动式的管道运算
1 2 3 4 echo "e(2)" | bc #以管道的方式把计算公式传给bc,bc计算后返回结果 echo "obase=2;7" | bc #多表达式同行,用;隔开 var_name=`echo "e(2)" | bc` #使用反引号给变量赋值 var_name=$(echo "e(2)" | bc) #使用$()给变量赋值,但不是所有linux系统都支持
非互动式输入重定向bc运算
不常用,略
流程控制语句 if else 语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # # # if 语句if [[ $a > $b ]] then ehco "a>b" fi if [[ $a > $b ]] ;then ;fi #一行时,用;隔开,多命令同行都是用;隔开,下同 # if else 语句if [[ $a > $b ]] then echo "ture" else echo "false" fi # if elif else 语句if [[ $a > $b ]] then ehco "a>b" elif [[ $a == $b ]] then ehco "a=b" else ehco "a<b" fi
case 语句 1 2 3 4 5 6 7 8 9 10 11 12 13 # case 的匹配模式支持,数字,字符串,部分正则表达式:# *:类似default # 支持正则 # |:多条件 a=59 case $a in [1-5]?|[8-9]) echo "[1-5]" ;; *) echo "*" ;; esac
while 与 until 语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # until 与while 相反,false 时执行a=0 while ((a < 10)) do if (($a%2 == 0)); then echo "$a+=3" a=$[a+3] continue; fi echo "$a+=1" a=$[a+1] if (($a > 7)); then echo "$a>7" break; fi done # 无限循环 while true do done while : do done
for 语句 1 2 3 4 5 6 7 8 9 # 枚举遍历 for i in 1 2 3;do ; done # 枚举遍历数组 arr=(1 2 3) for i in ${arr[@]};do echo $i; done # 范围遍历 for i in {1..100};do ;done # 类C遍历 for((i=1;i<100;i++));do ;done
select 语句 1 2 3 4 5 6 7 # 用于交互式的菜单选择,没有结束条件,只能使用break 跳出 # 会输出菜单项在控制台上供选择 # 经常配合case 使用 select var in itme1 itme2 itme3 do break; done
函数 系统函数
basename
:获取文件名
dirname
:获取文件所在目录
普通函数语法
shell函数与shell程序的区别:外部脚本文件在新进程中运行,函数在原进程运行
1 2 3 4 5 6 7 8 9 10 11 12 # 函数定义 [ function ] fun() { [return 返回值] #返回值的范围在[0-255];无返回值,返回最后一条命令的结果, } # 函数调用 fun 参数1 参数2 参数3 ... a=$? #获取返回值 # 与shell程序一样 使用$1 $2 $3 $*等获取参数
输入输出重定向 默认输入输出
文件名
类型
文件描述符
stdin
标准输入
0
stdout
标准输出
1
stderr
标准错误
2
重定向语法
命令
作用
> file ; < file
覆盖 方式重定向
>> file
追加方式重定向
< file1 >file2
从file1读取,结果输出到file2
fd> file ; fd >>file
把fd的数据重定向到文件中
> file fd1>&fd2
两个fd都输出到fd中
Shell 工具
cut工具:按列分割,并提取
sed工具:字段增删改查
awk工具:按表格处理数据
sort工具:排序
常用脚本 一键进入docker容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 svr=""; subCond="" arr=$(docker ps | grep $svr | grep -v $subCond | awk '{print $1}'); if [[ ${#arr[@]}>1 ]]; then docker ps | grep $svr | grep -v $subCond; read -p "please input CONTAINER ID:" contid; else contid=${arr[0]}; fi; if [[ -n $contid ]]; then docker exec --privileged -u root -it $contid bash; else echo "no find $svr"; fi