欢迎访问我的博客,你的支持,是我最大的动力!

shell编程_代码片断

Linux 小马奔腾 461℃ 评论
目录:
[显示]

脚本必须由 root 用户权限运行

系统可用的shell,cat /etc/shells

source script.sh 或 . script.sh (注意点.后有一空格),读入并执行脚本

sh<script.sh 或 cat script.sh|sh  也可执行脚本

常规变量字符串加双引号,且等号前后不能有空格
强引用(所见即所得)加单引号
命令的引用,用反引号
中括号两端至少要有一个空格

shell变量

环境变量:
TMOUT=3600 # 退出前超时时间
set 输出所有变量,包括全局和局部变量
unset 消除本地变量或环境变量
env 仅显示全局变量
declare 输出所有变量、函数、整数、已导出的变量

设置环境变量:
export 变量名=value
变量名=value ;export 变量名
declare -x 变量名=value

用户环境变量
/root/.bashrc /root/.bash_profile
全局环境变量
/etc/profile /etc/bashrc /etc/profile.d/

设置登录提示信息
/etc/motd  添加字符
/etc/profile.d/下放置脚本,不需要给执行权限

用户登录系统时,环境变量加载顺序:
/etc/profile -> /etc/profile.d/ -> $HOME/.bash_profile -> $HOME/.bashrc -> /etc/bashrc
非登录时,如手动执行 bash :
$HOME/.bashrc -> /etc/bashrc

把命令结果作为变量内容赋值:
变量名=ls
变量名=$(ls)

当变量后连接有其他字符串时,必须给变量加上大括号:
${dbname}_tname

awk 'BEGIN {print "'$ETT'"}'  # 注意 awk 中的用法非常特殊

/etc/init.d/functions 函数库

shell变量进阶

shell位置参数变量
从命令行、函数、脚本执行处传递参数

位置变量 说明
$0 获取脚本文件名
若执行脚本包含路径,则包括脚本路径
$n 获取第n个参数,n=1..9
若n>9,需使用大括号,${10}
$# 获取参数总个数
$* 获取所有参数,不加引号与$@相同
加引号 "$*" 表示将所有参数视为单个字符串,相当于"$1 $2 $3"
$@ 获取所有参数,不加引号与$*相同
加引号 "$@" 表示将所有参数视为不同独立字符串,相当于"$1" "$2" "$3"

echo \${1..15}

使用set设置位置参数
set -- "i am" handsome boy.
# -- 表示清除所有参数变量 重新设置后面的参数变量
# 设置了三个参数变量 可通过 $# $1 $2 $3 读取到
# for i;do echo $i;done -> for i in "$@";do echo $i;done  注意$@的双引号

shift 将位置参数移位(左移)

shell状态变量

状态变量 说明
$? 获取上一个指令执行状态返回值 0为成功
$$ 获取当前执行shell脚本的进程号 PID
$! 获取上一个在后台工作的进程的进程号 PID
$_ 获取之前执行的命令或脚本的最后一个参数

在脚本中,exit 数字,会返回该数字给 $?
在函数里,return 数字,会返回该数字给 $?

保证任务脚本只有一个实例在执行
当新脚本执行时,必须关闭未运行完或未退出的上一次同名脚本进程

shell内置命令
1、echo
参数:
-n 不换行输出
-e 解析转义字符,类似于 printf命令
2、eval
eval args
将args组合成一个新的命令并执行
3、exec
不创建子进程,执行指定的命令,执行完成后,进程(最初始的shell)终止
exec打开文件后,read命令每次都会将文件指针移动到文件下一行进行读取,直到文件末尾

4、read
从标准输入读取信息
5、shift
使变量左移 $2 -> $1

shell变量子串

表达式 说明
${parameter} 返回变量内容
${#parameter} 返回变量长度(按字符)
${parameter:offset} 返回offset开始到结尾的子串,offset值0表示完整串
${parameter:offset:length} 返回offset开始且长度为length的子串
${parameter#word} 开头开始删除最短匹配的word子串,必须从开头开始匹配,支持*通配符
${parameter##word} 开头开始删除最长匹配的word子串
${parameter%word} 结尾开始删除最短匹配的word子串,必须从结尾开始匹配,支持*通配符
${parameter%%word} 结尾开始删除最长匹配的word子串
${parameter/pattern/string} 使用string替换第一个匹配的pattern
${parameter//pattern/string} 使用string替换所有匹配的pattern

# 打印变量长度方法
# echo $OLDBOY|wc -L
# echo ${#OLDBOY}  速度最快
# expr length "$OLDBOY"   利用expr的length函数
# echo $OLDBOY|awk '{print length($0)}'  利用awk的length函数

shell特殊扩展变量

表达式 说明
${parameter:-word} parameter变量未定义或为空时,返回备用值word
${parameter:=word} parameter变量未定义或为空时,设置parameter值为word
${parameter:?word} parameter变量未定义或为空时,将word值作为标准错误输出
可捕捉由变量未定义而导致的错误
${parameter:+word} parameter变量未定义或为空时,什么都不做
parameter变量存在值时,使用word字符串替换变量的值
冒号:是可选的,表示为空,若没有:则仅判断未赋值(未定义)
变量的数值计算

++ -- 增加及减少,可前置也可放在变量结尾,位置表示了执行顺序
变量a在运算符前,输出表达式值为a,然后a自增或自减
变量a在运算符后,输出表达式会先自增或自减,表达式的值是自增或自减后的a的值

Shell常用算术运算命令

运算命令 说明
(()) 用于整数运算,效率很高
let 用于整数运算,类似于(())
expr 可用于整数运算,还有其他额外功能
bc 计算器程序,适合整数及小数运算
$[] 用于整数运算
awk 可用于整数运算,也可用于小数运算
declare 定义变量值和属性,-i参数可用于定义整形变量,做运算

((i=i+1)),运算后赋值,将i+1的值赋给i
i=$((i+1)),在双括号前加$,表示取运算结果
((8>7&&5==5)),可进行比较操作,结果1为真,0为假
echo $((2+1)),输出运算结果
myvar=99;echo $((myvar+1)),双括号中的变量可加$号也可以不加
双括号中的空格不影响,可有也可以没有

# 判断输入的字符串是否为数字
[ -n "echo $input|sed 's/[0-9]//g'" ]  判断字符串去掉数字后是否为空 -n 是否为空

let i=i+8 等同于 ((i=i+8)) 但后者效率更高

wget --timeout=5 --tries=2 http://www.baidu.com -q -O /dev/null

wget --spider --timeout=10 --tries=2 www.baidu.com &>/dev/null
curl -s -o /dev/null http://www.baidu.com
# -s 沉默模式 -o 输出到

expr 用于计算
运算符及用于计算的数字左右都至少要有一个空格
expr做计算时,变量或字符串必须是整数,否则会报错,可以用这一特性判断字符串是否为整数(将一个未知的变量和一个已知的整数相加,看返回值)
expr 2 + 2
expr 2 \* 2    #星号需要转义
expr $1 + 1 >/dev/null 2>&1
expr $1 + 1 &>/dev/null

expr 判断文件扩展名是否符合要求
expr "$L_ID_FILE" : ".*\.pub$"
# 若$L_ID_FILE符合.pub结尾的格式,则$?返回值为0,否则返回值不为0

expr 计算字符串长度
expr length "$char"
# 其他方法
echo ${#char}
echo ${char}|wc -L
echo ${char}|awk '{print length($0)}'

bc 计算器
echo 3+5|bc
echo 3.3+5.5|bc   #支持小数计算
echo "scale=2;355/113"|bc  #保留两位小数

seq -s "+" 10
## 1+2+3+4+5+6+7+8+9+10
echo {1..10}|tr " " "+"

awk 实现计算
适合小数和整数,小数运算很精确
echo "7.7 3.8"|awk '{print ($1-$2)}'

$[] 运算
i=5;i=$[i+6];echo $i
echo $[4+5]

Shell 条件测试与比较

条件测试常用语法

条件测试语法 说明
test <测试表达式> test和表达式间至少一个空格
[ <测试表达式> ] []边界和内容之间至少一个空格
-a -o -gt -lt 等
[[ <测试表达式> ]] [[]]边界和内容之间至少一个空格,可以使用通配符进行模式匹配
&& || < > 等
((<测试表达式>)) (())两端不需要有空格,用于对整数的关系运算

test -f file && echo true || echo false  #若文件存在且为普通文件,输出true,否则输出false

&&和||的两端可以有空格,也可以无空格

常用文件测试操作符

操作符 注解 说明
-d directory 目录
-f file 普通文件
-e exist 存在,不区分是文件还是目录
-r read 可读,用户权限位,若用户是root则固定为真
-s size 大小不为0
-w write 可写,用户权限位,若用户是root则固定为真
-x executable 可执行,用户权限位
-L link 链接文件
f1 -nt f2 newer than 修改时间较新
f1 -ot f2 older than 修改时间较旧

测试文件读写执行属性时,不只看文件属性,还要看成当前执行测试的用户是否真的可以操作文件(例如 root 就比较特殊)
测试时,若变量不加双引号,测试结果可能不正确

字符串测试操作符

操作符 说明
-n "str" 字符串长度不为0时为真
-z "str" 字符串长度为0时为真
"str1" = "str2" 也可以使用 == 等号两端有空格
"str1" != "str2" 等号两端有空格

测试字符串,一定要将字符串加双引号再作比较;字符串比较时,等号两端要有空格

整数二元比较操作符

-eq -> 相等
-ne -> 不等
-gt  -> 大于
-ge -> 大于等于
-lt   -> 小于
-le  ->  小于等于

逻辑操作符

在[]和test中使用:-a -o !
在[[]]和(())中使用: && || !

if 条件语句

获取HTTP响应码
curl -I -s -w "%{http_code}\n" -o /dev/null http://www.baidu.com
curl -I http://www.baidu.com 2>/dev/null | head -1 | egrep "200|302|301" | wc -l

chkconfig管理

Shell函数

执行函数直接输入函数名
函数定义必须在要执行的程序前面定义或加载
return是退出函数 exit是退出脚本
函数内可使用local定义局部变量,作用域仅函数体内

系统函数文件 /etc/init.d/functions
加载函数库:
[ -f /etc/init.d/functions ] && . /etc/init.d/functions || exit 1

case条件语句

grep精确过滤单词:
grep -w "name" app.yaml
grep "\bname\b" app.yaml  # \b边界标识符
grep "^name$" app.yaml     # 单行

while循环和until循环

sleep 1 == usleep 1000000  都表示休息1秒

脚本运行相关说明

用法 说明
sh xx.sh & 把脚本放到后台执行
ctrl+c 停止执行
ctrl+z 暂停执行
bg 把脚本或任务放到后台执行
fg 把脚本或任务放到前台执行
有多个后台任务时 fg + 任务编号
jobs 查看当前执行的脚本或任务
kill 关闭执行的脚本任务,kill %任务编号

pgrep 查找匹配条件的进程,返回进程号列表

while循环按行读取文件

for和select循环

seq 5 -1 1  #生成数字序列 起始数字5 步长-1 结束数字1
# 5\n4\n3\n2\n1\n

rename "gif" "txt" *.gif     #批量重命名

select循环语句主要作用是创建菜单,每项前会有数字加右小括号,并有提示符#?要求用户输入数字
PS3系统环境变量控制循环的提示符
REPLY变量是菜单项对应的数字

循环控制及状态返回值

条件与循环控制及程序返回值

命令 说明
break n 若省略n则跳出整个循环,n表示跳出循环的层数
continue n 若省略n则跳过本次循环,忽略本次循环的剩余代码
n表示退到第几层继续循环
exit n 退出程序,n为返回值
return n 退出函数,n为函数返回值

为服务器临时配置多个IP:
方式一:关闭会报错
ifconfig ens32:0 10.0.0.10/24 up
ifconfig ens32:0 10.0.0.10/24 down
方式二:推荐
ip addr add 10.0.0.10/24 dev ens32 label ens32:0
ip addr del 10.0.0.10/24 dev ens32 label ens32:0

Shell数组

下标从0开始

array=(value1 value2 value3)
echo ${array[*]}   echo ${array[@]}    #输出全部元素值

array=([3]=two [4]=one)                #通过下标赋值
array[0]=a;array[1]=b;array[2]=c    #分别定义变量赋值
array=($(命令))  array=(命令)      #将命令输出结果作为数组内容

unset 数组[下标]   #清除数组元素
echo ${array[@]:1:3}    #截取1到3号数组元素
echo ${array[@]/1/b}   #将数组中1替换为b,原数组不会修改,替换的是显示的值,全部替换

array=(one two three four five)
echo ${array[@]#o*}        #从左边开始匹配最短的数组元素 o ,并删除
echo ${array[@]##o*}      #从左边开始匹配最长的数组元素 o ,并删除
echo ${array[@]%f*}        #从右边开始匹配最短的数组元素 f ,并删除
echo ${array[@]%%f*}     #从右边开始匹配最长的数组元素 f ,并删除

Shell脚本开发规范

若要在脚本中使用中文,添加
export LANG="zh_CN.UTF-8"  或 "en_US.UTF-8"

定时任务执行shell时,最好在shell里重新定义全局变量,否则可能会出现问题
引用变量时,若变量前后都有字符,需使用 ${VAR} 大括号
变量为字符串时,添加双引号,"$var"
变量为整数时,不需要使用双引号,$var

Shell脚本的调试

yum install dos2unix
dos2unix shell.sh

sh [-nvx] shell.sh
选项:
-n 不执行脚本,仅查询语法是否有问题,并给出错误提示
-v 执行脚本时,先显示要执行的内容,再执行,若有错误也会给出错误提示
-x 将执行的脚本内容及输出显示到屏幕上,用于调试

set|grep PS4
# PS4='+ '  默认PS4系统变量是加号 +
可以修改,使其显示行号
export PS4='+${LINENO}'   将该行添加到被测试脚本中,在调试时可显示行号

set -n 读命令但并不执行
set -v 显示读取的所有行
set -x 显示所有命令及其参数

set -x 开启调试功能,set +x 关闭调试功能

bashdb,类似GDB的调试工具,可完成对脚本的断点设置、单步执行、变量观察等功能
shellcheck,可检查sh/bash脚本和命令语法的小工具,http://www.shellcheck.net/

linux信号及trap命令

# 显示所有信号 共64个信号量
kill -l 或 trap -l

信号 说明
HUP 1 挂起,通常因终端掉线或用户退出而引发
INT 2 中断,通常因按下 ctrl+c 组合键而引发
QUIT 3 退出,通常因按下 ctrl+\ 组全键而引发
ABRT 6 中止,通常因某些严重的执行错误而引发
ALRM 14 报警,通常用来处理超时
TERM 15 终止,通常在系统关机时发送
TSTP 20 停止进程的运行,通常因按下 ctrl+z 组合键而引发

通常需要忽略的信号:1,2,3,20,15 HUP,INT,QUIT,TSTP,TERM

trap用于在接收到信号后采取指定的行动,如在程序被中断时完成清理工作,屏蔽某些信号等
使用信号时需省略 SIG 前缀
trap command signal

stty -a 可列出中断信号与键盘的对应关系

trap "" 2    此时ctrl+c无任何反应
trap ":" 2   恢复ctrl+c原始功能

trap 'find /tmp -type f -name "xxx_*" |xargs rm -f && exit ' INT   触发信号后清理文件

利用信号防止用户中断信号在跳板机上操作
首先创建免密登录,然后放置脚本
echo '[ $UID -ne 0 ] && . /server/scripts/jump.sh' >/etc/profile.d/jump.sh
非root用户登录时,会自动执行该脚本

expect 自动化交互式程序

yum install expect

1、spawn 命令
spawn [选项] [需要自动交互的命令或程序]
-open 启动文件进程
-ignore 忽略某些信号
spawn ssh root@192.168.1.1 uptime
2、expect 命令
expect 表达式 [动作]
-re 使用正则表达式匹配
expect "*passwork" {send "123456\r"}
expect eof  表示expect结束

3、send 命令
-i 指定spawn_id 向不同的spawn_id进程发送命令,多程序控制的参数
-s 控制发送的速度,要与expect中的变量send_slow相关联
4、exp_continue 命令
继续匹配,用于匹配多次字符串
5、send_user 命令
打印expect脚本信息,类似echo
6、exit 命令
直接退出expect脚本
还可以在关闭前执行一些清理工作,如
exit -onexit {send_user "Good bye.\n"}

expect 程序变量
set 变量名 变量值
打印变量
puts $变量名

特殊参数变量
$argv 表示参数数组,第一个参数 [lindex $argv 0]
$argc 表示传参的个数
$argv0 表示脚本的名称

expect中的if条件语句

expect 关键字

1、eof 关键字
匹配结束符
2、timeout 关键字
全局时间控制开关 0表示立即超时 -1表示永不超时
set timeout 30  设置30秒超时

并发ping

并发ping

网站文件修改监控

find /var/html/www -type f|xargs md5sum >/opt/zhiwen.db.ori
find /var/html/www -type f >/opt/wenjian.db.ori
md5sum -c --quiet /opt/zhiwen.db.ori
diff /opt/wenjian.db*

子shell相关

使用 & 可产生子shell
由 & 产生的子shell可直接引用父shell定义的本地变量
由 & 可实现多线程并发功能

使用 | 管道可产生子shell
由 | 管道产生的子shell可直接引用父shell定义的本地变量

使用 () 可产生子shell
由 () 产生的子shell可直接引用父shell定义的本地变量

使用 exec 调用脚本后,被调用的脚本与父脚本在同一个shell内执行,但父脚本中exec执行之后的脚本内容不会再执行,即执行完exec就退出
使用 source . 则没有exec的问题,source之后的父脚本中的内容仍然会执行

部分命令

lsattr 查看文件扩展属性
chattr 修改文件扩展属性
rev 反向输出文件内容
dmesg 显示开机启动信息
stat 显示文件或文件系统状态
mkswap swapon swapoff  虚拟内存相关
sync 将内存缓冲区数据写入磁盘
lastlog 显示所有用户最近一次登录信息
last 显示登入系统的用户
users 显示当前登录系统的用户列表
killall 通过进程名终止进程
pkill 通过进程名终止进程
pgrep 查找匹配条件的进程

 

整理于 《跟老男孩学Linux运维:Shell编程实战 2017.1》

 

转载请注明:轻风博客 » shell编程_代码片断

喜欢 (2)or分享 (0)