公司动态
Linux进阶打怪:Shell编程保姆级入门指南
提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、先搞懂Shell到底是什么第一个Shell脚本Hello World脚本的两种执行方式二、Shell变量新手坑最多的地方1. 系统自带的变量2. 自定义变量记住“等号两边没空格”3. 环境变量全局生效的变量4. 位置参数变量给脚本传参数5. 预定义变量Shell提前定义好的三、Shell运算符算数运算怎么写四、条件判断逻辑控制的基础基本语法常用判断条件1字符串比较2整数比较3文件权限判断4文件类型判断if分支语句case分支语句五、循环语句批量操作的神器1. for循环写法1遍历参数/列表写法2类C语言循环2. while循环六、read读取输入让脚本可以交互七、Shell函数封装复用代码1. 两个超实用的系统函数2. 自定义函数八、实战案例MySQL定时自动备份需求脚本实现设置定时执行总结1、脚本基础2、四大变量3、算数运算4、条件判断分支语句5、循环6、交互输入read7、函数8、企业实战MySQL定时备份前言这篇博客我就把Shell编程从入门到实战的核心内容全部整理出来包括新手最容易踩的语法坑、高频必学的语法点、还有一个企业里真的会用的MySQL定时备份实战案例。全是自己踩坑总结出来的干货建议收藏学的时候对着敲一遍基本就能上手用哩一、先搞懂Shell到底是什么很多人学了半天Shell都没搞明白它到底是啥。其实一句话就能说清Shell就是一个命令行解释器是我们和Linux内核沟通的翻译官。我们在终端敲的cd、ls这些命令本质上都是先发给Shell再由Shell解析后调用内核执行。而Shell编程就是把一堆要执行的Linux命令按照逻辑顺序写进一个文件里让系统自动批量执行不用我们手动一条一条敲。Linux里最常用的Shell就是Bash也是我们学习的重点。我们写的脚本文件通常以.sh结尾这只是个约定俗成的标识其实不影响执行但规范起见还是建议加上。第一个Shell脚本Hello World新手写第一个脚本大概率会踩两个坑忘了加脚本声明、忘了加执行权限。我当初两个坑全踩了印象极其深刻。一个标准的脚本长这样#!/bin/bash# 我的第一个Shell脚本echoHello World!第一行#!/bin/bash是必须的告诉系统这个脚本要用Bash解释器来执行#开头的是注释脚本运行的时候会自动忽略。脚本的两种执行方式赋予权限后直接执行推荐# 给脚本添加可执行权限chmodux hello.sh# 相对路径执行./hello.sh# 也可以用绝对路径执行/root/shellCode/hello.sh用sh命令直接调用不用加权限shhello.sh这种方式本质是直接用sh解释器去读文件所以不需要文件本身有执行权限临时测试的时候很方便。二、Shell变量新手坑最多的地方Shell的变量分为四大类系统变量、自定义变量、环境变量、特殊变量其中细节特别多尤其是空格规则新手一不注意就报错。1. 系统自带的变量Linux内置了很多现成的变量比如$HOME当前用户家目录、$PWD当前所在绝对路径、$SHELL当前解释器、$USER当前用户名。想查看所有系统变量直接输set就行会列出当前Shell里所有的变量和函数。运行实例如下2. 自定义变量记住“等号两边没空格”这是我踩的第一个大坑写A 100报错了半天后来才知道Shell里变量赋值等号左右绝对不能有空格。#!/bin/bash# 正确写法等号两边无空格A100# 输出变量要加$符号echoA$AechoA$A# 撤销变量用unsetunsetAecho撤销后A$A# 声明只读变量不能修改也不能撤销readonlyB2echo只读变量B$B还有几个命名规则要记住变量名只能由字母、数字、下划线组成不能以数字开头变量名习惯全大写算是行业默认规范想把命令的执行结果赋值给变量有两种写法# 写法1反引号不推荐容易和单引号搞混Cdate# 写法2$()推荐清晰易读D$(date)3. 环境变量全局生效的变量如果想让一个变量在所有Shell脚本里都能用就要把它设成环境变量。我们之前配置JDK的时候改的/etc/profile里面写的就是全局环境变量。配置步骤很固定用export 变量名变量值把变量导出为环境变量执行source 配置文件让修改立刻生效不用重启系统用echo $变量名就能查到变量值了。4. 位置参数变量给脚本传参数我们写的脚本不可能永远写死内容很多时候需要运行的时候传参数进去这时候就要用到位置参数变量。常用的就这几个变量作用$0脚本本身的文件名$n第n个输入参数n从1开始10以上要写成${10}$*所有输入参数当成一个整体看待$所有输入参数每个参数相互独立$#输入参数的总个数举个例子就懂了写个脚本position.sh#!/bin/bashecho脚本文件名$0echo第一个参数$1echo第二个参数$2echo所有参数(整体)$*echo所有参数(独立)$echo参数总个数$#运行实例如下运行./position.sh 100 200输出结果一目了然。这里$*和$的区别在后面for循环里会体现得更明显。5. 预定义变量Shell提前定义好的这几个变量不用自己定义直接就能用写脚本判断状态的时候超实用$$当前脚本运行的进程号PID$!后台运行的最后一个进程的进程号$?上一条命令的执行状态0代表执行成功非0代表执行失败尤其是$?写脚本的时候判断上一步有没有执行成功全靠它。三、Shell运算符算数运算怎么写Shell里的算数运算不能直接写12有三种固定写法我个人最推荐第二种省事又不容易错。$((运算式))$[运算式]✅ 推荐expr 运算式举个例子计算3*(51)#!/bin/bash# 写法1RESULT1$((3*(51)))echo结果1$RESULT1# 写法2最简洁推荐用RESULT2$[3*(51)]echo结果2$RESULT2# 写法3expr运算符两边必须有空格乘号要转义TEMPexpr51RESULT3expr3\* $TEMPecho结果3$RESULT3运行实例如下运行结果为expr写法特别麻烦空格、转义符很容易写错日常写脚本基本都用$[]简单粗暴。四、条件判断逻辑控制的基础基本语法[条件表达式]⚠️ 巨坑提醒中括号两边必须有空格[ab]这么写必错正确写法是[ a b ]。条件为空的时候返回false有内容就返回true所以[ abc ]的结果是真[ ]是假。常用判断条件1字符串比较判断两个字符串是否相等!判断两个字符串是否不相等2整数比较-lt小于less than-gt大于greater than-le小于等于-ge大于等于-eq等于-ne不等于3文件权限判断-r有读权限-w有写权限-x有执行权限4文件类型判断-f存在且是普通文件-e文件/目录存在-d存在且是目录if分支语句if语句的结尾是fi就是if反过来写刚开始记的时候觉得特别有意思。if分支语句中结尾fi必须加# 单分支if[条件]then执行代码fi# 多分支if[条件1]then代码1elif[条件2]then代码2else代码3fi# 判断文件是否存在if[-f文件的绝对路径]then代码fi举个经典例子输入分数判断等级#!/bin/bashif[$1-ge80]thenecho优秀elif[$1-ge70]thenecho良好elif[$1-ge60]thenecho及格elseecho不及格fi运行结果如下case分支语句case的结尾是esac同样是反过来记。每个分支结尾要写两个分号;;。case$变量名in值1)代码1;;值2)代码2;;*)默认执行的代码;;esac执行结果如下五、循环语句批量操作的神器1. for循环for循环有两种常用写法适用场景不一样。写法1遍历参数/列表for变量in值1 值2 值3do循环体done这个写法特别适合遍历输入参数这里就能看出$*和$的区别了#!/bin/bashecho----测试\$*----foriin$*doecho参数$idoneecho----测试\$----foriin$doecho参数$idone运行./test.sh 1 2 3$*只会输出一行“参数1 2 3”而$会输出三行分别是1、2、3。运行结果如下写法2类C语言循环for((初始值;循环条件;变量变化))do循环体done运行结果如下经典例题求1到100的和#!/bin/bashSUM0for((i1;i100;i))doSUM$[$SUM$i]doneecho1-100的和是$SUM运行结果如下2. while循环while循环和其他语言逻辑一样条件满足就一直循环。while[条件]do循环体done同样用求1到100的和举例#!/bin/bashSUM0i1while[$i-le100]doSUM$[$SUM$i]i$[$i1]doneecho总和是$SUM六、read读取输入让脚本可以交互如果想让脚本运行的时候提示用户输入内容就要用到read命令。两个最常用的参数-p指定提示文字-t指定等待超时时间单位秒超时就不等了举个例子#!/bin/bash# 提示用户输入不限时间read-p请输入第一个数字NUM1# 提示用户输入10秒内没输入就跳过read-t10-p请输入第二个数字10秒内NUM2echo两个数的和是$[$NUM1$NUM2]七、Shell函数封装复用代码Shell里有系统自带的工具函数也可以自己定义函数。1. 两个超实用的系统函数basename从完整路径里抠出文件名basename/home/test/a.txt# 输出 a.txtbasename/home/test/a.txt .txt# 去掉后缀输出 adirname从完整路径里抠出文件所在的目录路径dirname/home/test/a.txt# 输出 /home/test处理文件路径的时候这两个函数巨好用不用自己写字符串切割。2. 自定义函数Shell函数的语法和其他语言有点不一样参数不用写在括号里调用的时候直接跟在函数名后面。#!/bin/bash# 定义函数functiongetSum(){SUM$[$n1$n2]echo两数之和是$SUM}# 读取用户输入read-p输入第一个数n1read-p输入第二个数n2# 调用函数参数直接写在后面getSum$n1$n2⚠️ 注意函数必须定义在调用前面Shell是从上往下执行的先定义后调用。八、实战案例MySQL定时自动备份学了这么多语法总得做点实际的东西。这个MySQL备份脚本是企业里真的会用的写完特别有成就感。需求每天凌晨2:30自动备份MySQL数据库备份文件以备份时间命名打包成tar.gz格式自动删除10天前的旧备份文件备份开始和结束给出提示。脚本实现#!/bin/bash# 备份文件存放目录BACKUP/data/backup/db# 获取当前时间格式年月日_时分秒DATETIME$(date%Y-%m-%d_%H%M%S)echo开始备份时间$DATETIME# 数据库配置HOSTlocalhostDB_USERrootDB_PW你的数据库密码DATABASE要备份的库名# 如果备份目录不存在就自动创建[!-d${BACKUP}/${DATETIME}]mkdir-p${BACKUP}/${DATETIME}# 执行数据库备份并压缩mysqldump -u${DB_USER}-p${DB_PW}--host${HOST}-q-R--databases${DATABASE}|gzip${BACKUP}/${DATETIME}/${DATETIME}.sql.gz# 切换到备份目录把整个文件夹打包成tar.gzcd${BACKUP}tar-zcvf$DATETIME.tar.gz${DATETIME}# 删掉原文件夹只保留压缩包rm-rf${BACKUP}/${DATETIME}# 删除10天前的备份文件find${BACKUP}-atime10-name*.tar.gz-execrm-rf{}\;echo备份完成文件$DATETIME.tar.gz设置定时执行脚本写好之后用crontab设置定时任务就能全自动运行了# 编辑定时任务crontab-e# 添加一行每天凌晨2点30分执行脚本302* * * /usr/sbin/mysql_db_backup.sh总结ShellBash是Linux命令行解释器Shell脚本就是把多条Linux命令编写到.sh文件实现批量自动化执行是运维自动化的核心工具。1、脚本基础脚本首行声明#!/bin/bash指定Bash解释器。#代表注释。两种执行方式chmod ux xxx.sh ./xxx.sh添加执行权限后运行推荐sh xxx.sh直接调用解释器不需要执行权限2、四大变量系统变量$HOME、$PWD、$USERset查看全部系统变量。自定义变量A100等号两边不能有空格取值$A撤销unset A只读readonly B2。命令结果赋值D$(date)推荐不推荐反引号date。环境变量export 变量名值导出全局变量source 配置文件生效。位置参数变量变量作用$0脚本文件名$1 $2...${10}第1、2、10个参数$*全部参数作为一整个字符串$全部参数每个参数独立循环常用$#传入参数总个数预定义变量$$当前脚本PID$!最后一个后台进程PID$?上一条命令返回状态0成功非0失败脚本判断必备。3、算数运算优先用$[表达式]简洁方便也可用$((表达式))expr运算符前后必须空格乘号\*转义。res$[3*(51)]4、条件判断语法[ 条件 ]中括号内侧必须留有空格。字符串相等、!不等整数-lt小于、-gt大于、-le小于等于、-ge大于等于、-eq等于、-ne不等于文件-f普通文件、-d目录、-e存在权限-r -w -x分支语句if语句结束标记fiif[条件];then...elif[条件];then...else...ficase语句结束标记esac每个分支末尾;;。5、循环for循环遍历for i in 值1 值2 值3; do ... done区分$*与$C风格计数for((i1;i100;i));do ... donewhile循环条件成立循环while[条件]dodone6、交互输入read-p提示文字-t超时秒数read-p提示文字numread-t10-p10秒超时输入num27、函数内置工具basename获取文件名dirname获取目录路径自定义函数必须先定义后调用参数直接跟函数名后面不写括号。functionfun(){}fun 参数1 参数28、企业实战MySQL定时备份使用mysqldump做数据库备份配合gzip压缩find命令清理N天前过期备份配合crontab -e配置定时任务实现定时自动备份。高频踩坑汇总变量赋值等号不能加空格[ ]条件判断括号内部两侧必须空格if结尾fi、case结尾esac不能遗漏$*与$双引号包裹下循环行为不一样函数必须写在调用代码之前$?判断上一步执行结果自动化脚本必备