Linux中shell编程
一、Shell编程
1.1 常用符号解读
后台执行
简介
& 就是将一个命令从前台转到后台执行,使用格式如下:命令 &
示例:
后台执行休眠命令
[root@localhost ~]# sleep 10 &
就是开启这个服务让其在后台运行,你可以继续在当前终端操作,不卡顿
信息符号
信息简介
1 表示正确输出的信息
2 表示错误输出的信息
2>&1 代表所有输出的信息,也可以简写为 "&>"
示例1 - 符号演示:
标准正确输出重定向到zhengque文件
[root@localhost ~]# ls 1>> zhengque 标准错误输出重定向到errfile文件
[root@localhost ~]# ls 2>> errfile
示例2 - 综合演练
脚本文件内容
[root@localhost ~]# vim ceshi.sh-- 编辑ceshi.sh文件
#!/bin/bash
# 输出正确信息
echo '下一条错误命令'
# 执行错误命令,输出错误信息
dsfsafsafdsa
1 和 2 综合演练
[root@localhost ~]# /bin/bash ceshi.sh 1>> ceshi-ok 2>> ceshi-err
[root@localhost ~]# cat ceshi-ok
下一条错误命令
[root@localhost ~]# cat ceshi-err
ceshi.sh:行5: dsfsafsafdsa: 未找到命令
1.2 EOF原理
编写请假条
[root@localhost ~]# vim qingjiatiao.sh#!/bin/bash
# EOF演示请假条示例cat << EOF请假条
王老师:我因患急性空腹病,现在需要到火锅理疗,不能到学校上课,
请准假一天。恳请批准!请假人:李四6月1日
EOF执行脚本示例
[root@localhost ~]# bash qingjiatiao.sh请假条
王老师:我因患急性空腹病,现在需要到火锅理疗,不能到学校上课,
请准假一天。恳请批准!请假人:李四6月1日
示例二 - 多行文件输出
定制主机解析名信息
[root@localhost ~]# cat >> cs1 << EOF
10.0.0.13 k8s-master
10.0.0.14 k8s-node1
10.0.0.15 k8s-node2
EOF演示效果
[root@localhost ~]# cat cs1
10.0.0.13 k8s-master
10.0.0.14 k8s-node1
10.0.0.15 k8s-node2
EOF的使用便于我们同时操作几台终端,简化了操作
1.3 echo解读
基础知识:
OPTIONS:
-n 不要在最后自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:转义字符
\a 发出警告声;
\b 删除前一个字符;
\c 最后不加上换行符号;
\f 换行但光标仍旧停留在原来的位置;
\n 换行且光标移至行首;
\r 光标移至行首,但不换行;
\t 插入tab;
\v 与\f相同;
\ 插入\字符;
\0nnn 打印nnn(八进制)所代表的ASCII字符; 备注:数字0 不要理解成字母o
\xNN 打印NN(十六进制)所代表的ASCII字符;-–help 显示帮助
-–version显示版本信息
实践1 - 特殊符号的输出
使用 -e 选项启用转义字符的解析
[root@localhost ~]# echo -e "The 2021 State of DevOps Report\n\t- is here"
实践2 - 内容的拼接
使用 -n 选项启用信息输出不换行
[root@localhost ~]# echo -n hello;echo world
1.4 字体颜色
格式解读:
格式如下:echo -e "\033[字背景颜色;文字颜色m 字符串\033[0m"echo -e "\033[41;36m 显示的内容 \033[0m"
色彩 | 黑 | 红 | 绿 | 黄 | 蓝 | 紫 | 青 | 灰 |
---|---|---|---|---|---|---|---|---|
字体色 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
背景色 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
结束控制符
最后面控制选项说明
\033[0m 关闭所有属性 \033[1m 设置高亮度 \033[4m 下划线
\033[5m 闪烁 \033[7m 反显 \033[8m 消隐
注意:
\033 是八进制的ESCAPE字符,我们可以用 \e 来代替
实践1 - 字体颜色和背景颜色
字体颜色示例
echo -e "\033[30m 黑色字 \033[31m 红色字 \033[32m 绿色字 \033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[35m 紫色字 \033[36m 天蓝字 \033[37m 白色字 \033[0m"背景颜色示例
echo -e "\033[40;37m 黑底白字 \033[41;37m 红底白字 \033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[44;37m 蓝底白字 \033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[47;30m 白底黑字 \033[0m"
示例2:
定制跳板机的测试页面脚本
[root@localhost ~]# vim simple_jumpserver.sh
#!/bin/bash
# 功能:定制跳板机的展示页面
# 作者:wangshuji
# 版本:V0.1
# 联系:superopsmsb.comecho -e "\e[31m \t\t 欢迎使用跳板机"echo -e "\e[32m
-----------请选择你要登录的远程主机-----------1: 10.0.0.14 (nginx)2: 10.0.0.15 (tomcat)3: 10.0.0.19 (apache)q: 使用本地主机
----------------------------------------------
"'\033[0m'
echo -e "请输入您要选择的远程主机编号: "
1.5 printf格式化
基本语法
printf: printf [-v var] 格式 [参数]
格式化替换符
%s 字符串
%d,%i 十进制整数
%f 浮点格式
%c ASCII字符,即显示对应参数的第一个字符
%b 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义
%o 八进制值
%u 不带正负号的十进制值
%x 十六进制值(a-f)
%X 十六进制值(A-F)
%% 表示%本身
格式化转义符号
\a 警告字符,通常为ASCII的BEL字符
\b 后退
\c 抑制(不显示)输出结果中任何结尾的换行字符
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符
\\ 一个字面上的反斜杠字符
\ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd 表示1到3位的八进制值字符
格式化字符解释
– 将字段里已格式化的值向左对齐
空格 在正值前置一个空格,在负值前置一个负号
+ 总是在数值之前放置一个正号或负号,即便是正值也是
# 下列形式选择其一:
%o有一个前置的o; %x与%X分别前置的0x与0X;
%e,%E与%f总是在结果中有一个小数点; %g与%G为没有结尾的零。
0 以零填补输出,而非空白.这仅发生在字段宽度大于转换后的情况
实践1 - 替换符号演示
基本信息演示 - 单引号和双引号效果一样
[root@localhost ~]# printf "姓名:%s, 语文:%d, 数学:%d\n" "张三" 89 98
姓名:张三, 语文:89, 数学:98注意:相关信息会按照顺序依次替换到格式化的替换符位置
数字格式展示
[root@localhost ~]# printf '姓名:%s, 身高:%f米, 体重:%f公斤\n' "张三" 1.7 66
姓名:张三, 身高:1.700000米, 体重:66.000000公斤[root@localhost ~]# printf '姓名:%s, 身高:%.2f米, 体重:%.1f公斤\n' "张三" 1.7 66
姓名:张三, 身高:1.70米, 体重:66.0公斤
注意:通过 %.nf,n代表小数点后面的可显示的位数。
实践2 - 简单格式化
() 用于信息的批量化显示
[root@localhost ~]# printf "(%d %s)\n" 1 张三 2 李四 3 王五
(1 张三)
(2 李四)
(3 王五)printf默认不携带最后的换行
[root@localhost ~]# printf "(%d %s) " 1 张三 2 李四 3 王五
(1 张三) (2 李四) (3 王五) [root@localhost ~]#借助于echo的功能实现换行的效果
[root@localhost ~]# printf "(%d %s) " 1 张三 2 李四 3 王五; echo
(1 张三) (2 李四) (3 王五)
实践4 - 格式化补充
%s字符串格式化
[root@localhost ~]# printf '姓名:%-10s语文:%d, 数学:%d\n' "张三" 89 98 "李四" 87 97注意:%-10s,代表信息后面携带10个空格,便于格式化
%d数字格式补全
[root@localhost ~]# printf "%5d %s\n" 1 张三1 张三
[root@localhost ~]# printf "%05d %s\n" 1 张三
00001 张三
[root@localhost ~]# printf "%05d %s\n" 100 张四
00100 张四
注意:0的作用就是不用空格补全,而是用0填充,实现格式化
综合案例
学习目标
这一节,我们从 java部署、脚本定制、小结 三个方面来学习。
java部署
-- 创建目录
mkdir /data/{softs,server} -p
[root@localhost ~]# vim /data/scripts/java_install.sh
#!/bin/bash
# 功能: java环境的定制
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com# 定制基本信息
JAVA_SOFT='jdk-8u151-linux-x64.tar.gz'
JAVA_DIR='jdk1.8.0_121'
JAVA_NAME='java'
SERVER_HOME='/data/server'
SOFTS_HOME='/data/softs'
RED="echo -e \E[1;31m"
END="\E[0m"# 安装软件
tar zxvf $SOFTS_HOME/$JAVA_SOFT -C $SERVER_HOME
ln -s $SERVER_HOME/$JAVA_DIR $SERVER_HOME/$JAVA_NAME# 定制环境变量
cat >> /etc/profile << EOF
export JAVA_HOME=$SERVER_HOME/$JAVA_NAME
export PATH=\$JAVA_HOME/bin:\$PATH
EOF# 加载java环境变量文件
source /etc/profile# 检查效果
java -version > /tmp/txt 2>&1
java_version=$(grep version /tmp/txt | cut -d '"' -f2)# 信息显示
$RED---------$JAVA_NAME软件运行情况---------$END
printf "\033[32m%s:\033[33m%s\033[0m\n" "java软件版本" $java_version
$RED----------------------------------$END
1.6 脚本交互
read基础
read 从标准输入读取一行并赋值给特定变量REPLY。
read answer 从标准输入读取输入并赋值给变量answer。
read first last 从标准输入读取内容,将第一个单词放到first中,其他内容放在last中。
read -s passwd 从标准输入读取内容,写入passwd,不输入效果
read -n n name 从标准输入读取内容,截取n个字符,写入name,超过n个字符,直接退出
read -p "prompt" 打印提示,等待输入,并将输入存储在REPLY中。
read -r line 允许输入包含反斜杠。
read -t second 指定超时时间,默认是秒,整数
read -d sper 指定输入信息的截止符号
简单实践
示例1:
交互式接收用户信息
[root@localhost ~]# read
nihao-answer接收用户输入给一个临时变量
[root@localhost ~]# read answer
nihao-answer
[root@localhost ~]# echo $answer
nihao-answer接收多个信息,按照顺序交给不同的临时变量
[root@localhost ~]# read first last
first-1 last-2 end-3
[root@localhost ~]# echo $first
first-1
[root@localhost ~]# echo $last
last-2 end-3
示例二:
隐式接收用户输入信息
[root@localhost ~]# read -s password
[root@localhost ~]# echo $password
abcdefg
示例三:
通过 -p 参数提示用户输入的信心
[root@localhost ~]# read -p "请输入登录用户名: " user
请输入登录用户名: root
[root@localhost ~]# echo $user
root
示例4-限制用户输入信息
[root@localhost ~]# read -n 6 -p "sss: " aaa
sss: 123456[root@localhost ~]# read -n 6 -p "只接收6个字符,超过自动退出: " string
只接收6个字符,超过自动退出: 123456[root@localhost ~]#
[root@localhost ~]# echo $string
123456
注意:-p + -s 的组合会导致不会自动换行,可以结合 echo的方式实现换行
示例5:
[root@localhost ~]# read -t 5 -p "等待5秒后自动退出! " second
等待5秒后自动退出! 4
[root@localhost ~]# echo $second
4
[root@localhost ~]# read -t 5 -p "等待5秒后自动退出! " second
等待5秒后自动退出! [root@localhost ~]#
案例实践:
[root@localhost ~]# vim simple_login.sh
#!/bin/bash
# 功能: 模拟shell登录
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com# 清屏
clear# 输出提示信息
echo "---------------------------------"
# 交互输入登陆信息
read -p "请输入用户名:" account
read -s -t30 -p "请输入登录密码:" password
echo
echo "---------------------------------"
# 输出用户输入信息
printf "您输入的用户名:\e[31m%s\e[0m您输入的密码:\e[31m%s\e[0m\n" ${account} ${password}
跳板机实践
[root@localhost ~]# vim simple_jumpserver.sh
#!/bin/bash
# 功能:定制跳板机的展示页面
# 版本:v0.2
# 作者:书记
# 联系:www.superopsmsb.com# 跳板机的信息提示
echo -e "\e[31m \t\t 欢迎使用跳板机"echo -e "\e[32m
-----------请选择你要登录的远程主机-----------1: 10.0.0.14 (nginx)2: 10.0.0.15 (tomcat)3: 10.0.0.19 (apache)q: 使用本地主机
----------------------------------------------
"'\033[0m'# 由于暂时没有学习条件判断,所以暂时选择 q
read -p "请输入您要选择的远程主机编号: " host_index
read -p "请输入登录本地主机的用户名: " user# 远程连接主机
ssh $user@localhost
1.7 运算符
运算符基础
我们从 $[]、let、(())、$(())
、小结 五个方面来讲解
格式:
方法1:
$[计算表达式]
方法2:
a=$[变量名a+1]注意:
这里的表达式可以不是一个整体
简单示例:
简单运算
[root@localhost ~]# echo $[100/5]
20
[root@localhost ~]# echo $[ 2 + 5 ]
7变量参与运算
[root@localhost ~]# a=6
[root@localhost ~]# a=$[a+1]
[root@localhost ~]# echo $a
7运算结果取整
[root@localhost ~]# echo $[100/3]
33
let
格式:
let 变量名a=变量名a+1
注意:
表达式必须是一个整体,中间不能出现空格等特殊字符
简单示例:
简单运算
[root@localhost ~]# i=1
[root@localhost ~]# let i=i+7
[root@localhost ~]# echo $i
8let表达式必须是一个整体
[root@localhost ~]# let i = i * 2
bash: let: =: 语法错误: 期待操作数 (错误符号是 "=")
[root@localhost ~]# let i=i * 2
bash: let: anaconda-ks.cfg: 语法错误: 无效的算术运算符 (错误符号是 ".cfg")
[root@localhost ~]# let i=i*2
[root@localhost ~]# echo $i
$(())
格式:
echo $((变量计算表达式))
注意:
对于 $(())中间的表达式,可以不是一个整体,不受空格的限制
[root@localhost ~]# num1=34
[root@localhost ~]# echo $((num2=num1+34))
68
赋值运算进阶
简单实践
加法运算
[root@localhost ~]# echo $(( 4 + 4 ))
8
[root@localhost ~]# num1=3 num2=4
[root@localhost ~]# echo $(($num1 + $num2))
7减法运算
[root@localhost ~]# echo $((8-2))
6
[root@localhost ~]# echo $(($num2-$num1))
1乘法运算
[root@localhost ~]# echo $((8*2))
16
[root@localhost ~]# echo $(($num2*$num1))
12除法运算
[root@localhost ~]# echo $((8/2))
4
[root@localhost ~]# echo $(($num2/$num1))
1取余运算
[root@localhost ~]# echo $((8%3))
2
[root@localhost ~]# echo $(($num2%$num1))
1
案例实践-小学计算题
查看脚本内容
[root@localhost ~]# vim count_head_feet.sh
#!/bin/bash
# 功能:小学计算题目
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com# 定制普通变量
head="$1"
feet="$2"# 计算逻辑
# 每个头至少两只脚,多出的脚都是兔子的
rabbit_num=$(( ($feet - $head - $head) / 2))
chick_num=$[ $head - $rabbit_num ]# 结果输出
echo -e "\e[31m\t鸡和兔的数量\e[0m"
echo -e "\e[32m============================"
echo "鸡的数量: ${chick_num}"
echo "兔的数量:${rabbit_num}"
echo -e "============================\e[0m"
赋值运算
简介
这里的赋值运算,是一种进阶版本的复制操作,常见的样式如下:
样式1:+=、-=、*=、/=
- 在自身的基础上进行二元运算,结果值还是自己
样式2:++、--
- 在自身的基础上进行递增和递减操作,结果值还是自己
简单示例:
+=运算
[root@localhost ~]# num1=6
[root@localhost ~]# let value+=$num1 # 相当于 let value=value+$num1
[root@localhost ~]# echo $value
6-=运算
[root@localhost ~]# let value-=2 # 相当于 let value=value-2
[root@localhost ~]# echo $value
4*=运算
[root@localhost ~]# let value*=2 # 相当于 let value=value*2
[root@localhost ~]# echo $value
8/=运算
[root@localhost ~]# let value/=2 # 相当于 let value=value/2
[root@localhost ~]# echo $value
4
i++运算
[root@localhost ~]# value=9
[root@localhost ~]# let value++ # 相当于 let value=value+1
[root@localhost ~]# echo $value
10
[root@localhost ~]# let value++ # 相当于 let value=value+1
[root@localhost ~]# echo $value
11++i运算
[root@localhost ~]# let ++value # 相当于 let value=value+1
[root@localhost ~]# echo $value
12
expr计算
expr即可以做常见的整数运算,还可以做数字比较,字符串计算等操作。
格式:
数字场景:
expr 运算表达式
字符串场景:
match:用户获取匹配到字符串的长度
expr match 字符串 匹配内容
substr:截取字符串
expr substr 字符串 起始位置 截取长度
注意:起始位置值>=1
index:查找第一次匹配字符的位置
expr index 字符串 字符
length:计算字符串的长度
expr length 字符串
简单实践
数学运算[root@localhost ~]# expr 1 + 2 - 3 \* 4 / 5 + \( 6 - 7 \) \* 8
-7
[root@localhost ~]# x=1
[root@localhost ~]# expr $x + 4
5
字符串运算
用户获取匹配到字符串的长度
[root@localhost ~]# file=jdslkfajkldsjafklds
[root@localhost ~]# expr match $file "k.*j"
0
[root@localhost ~]# expr match $file ".*j"
13截取字符串
[root@localhost ~]# expr substr $file 0 4
[root@localhost ~]# expr substr $file 1 4
jdsl查找第一次匹配字符的位置
[root@localhost ~]# expr index $file b
0
[root@localhost ~]# expr index $file j
1计算字符串的长度
[root@localhost ~]# expr length $file
19