【运维知识高级篇】超详细的Shell编程讲解1(Shell作用+脚本书写方式+脚本执行方式+变量分类+变量配置文件+变量定义+Shell重要的位置变量+三种传参方式)

学习Shell编程对于一个运维来说至关重要,现在岗位上基本都要求运维,懂1门脚本语言,或是Shell或是python,今天我们就展开Shell编程的讲解,这也是运维知识高级篇的第一篇,带大家从基础运维向中级运维转变。

目录

Shell的作用

学习Shell编程必备知识

如何学好Shell编程

Shell入门

一、什么是Shell

二、什么是Shell脚本

Shell脚本书写方式

第一个Shell脚本

一、创建一个shell脚本

二、执行shell脚本的三种方式

变量

一、变量的含义

二、变量的分类

三、变量相关的配置文件

四、变量定义方式 

五、Shell重要的位置变量

六、变量三种传参方式 

扩展

一、直接传参

二、赋值传参

三、read交互式传参


Shell的作用

1、安装操作系统可以选择自动安装(无人值守安装软件cobbler、kickstart) 底层调用shell脚本
2、优化操作系统(防火墙优化 selinux关闭 SSH优化 加大文件描述符 修改默认YUM仓库 EPEL仓库 时间同步 关闭NetworkManager 安装常用软件 内核参数优化... ) 写入到脚本文件中
3、安装部署服务(Nginx Apache PHP MySQL Redis Tomcat....)写入脚本
4、业务数据统计(Linux命令) 统计好后可以定时发到领导邮箱,写入脚本+定时任务
5、大文件切割(防止日志文件过大) 写成shell脚本
6、辅助公司自研的(不成熟的)程序正常运行
7、监控 脚本取值+定时任务-->发送到邮箱
8、系统底层服务都是使用shell脚本,自研发程序或py程序
9、简化操作步骤

vim start_py.sh
nohup python3.5 test.py -redis-ip=172.16.1.51 -redis-port=6379 xxx &
vim stop_py.sh   
ps axu|grep test.py|grep -v grep|awk '{print $2}'|xargs kill -9

学习Shell编程必备知识

1、Linux基础命令,重点关注awk sed grep
2、正则表达式
3、熟练使用vim(各种快捷键)
4、Xshell远程连接工具

如何学好Shell编程

1、内容不多,主要是变量 比较表达式 if判断 for循环 while循环 流程控制语句 case语句 函数function 数组等等
2、先可以读懂别人的代码,进行简单的修改代码,能够独立编写简单的脚本,一开始可以先用命令堆积(熟练后使用语句)
3、多看案例,多看其他人编写的脚本,学习他人思路,变成自己思路
4、切忌拿来既用
5、代码的每行不是特别的理解的、使用中文注释
6、有一本适合自己的教材或者是详细的笔记
7、要有编程思维(来源于生活)

Shell入门

一、什么是Shell

Shell是命令解释器,Linux默认的Shell是: bash

Shell分交互式与非交互式

交互式:输入命令可以得到响应
非交互式:通过脚本运行Shell命令,无需等待用户输入命令

二、什么是Shell脚本

将基础命令写入到文件中称为shell脚本吗,文本中包含变量,判断语句,循环,数组等内容

Shell脚本书写方式

1、Shell脚本存放在固定目录
2、Shell脚本开头需要写解释器,默认使用的是bash
3、Shell脚本必须以.sh结尾
4、Shell脚本中最好不用中文做注释
5、Shell中成对的符号一次性书写完毕
6、Shell中语法一次书写完毕
7、切记不使用中文符号

第一个Shell脚本

一、创建一个shell脚本

[root@LB00 ~]# mkdir -p /server/scripts/Day01 
[root@LB00 ~]# cd /server/scripts/Day01
[root@LB00 Day01]# cat test.sh 
#!/bin/bash
echo "Hello World"

二、执行shell脚本的三种方式

第一种方式: 使用解释器执行脚本中的命令  在子shell中执行
[root@LB00 Day01]# sh test.sh 
Hello World
[root@LB00 Day01]# bash test.sh
Hello World

第二种方式: 使用路径的方式执行脚本 必须加x执行权限 在子shell中执行,分相对路径,绝对路径
[root@LB00 Day01]# chmod +x test.sh #增加了x权限,下面在敲路径时候才能用tab补齐
[root@LB00 Day01]# ./test.sh 
Hello World
[root@LB00 Day01]# /server/scripts/Day01/test.sh 
Hello World

第三种执行方式: 使用source或者.执行  在父shell中执行
[root@LB00 Day01]# source test.sh 
Hello World
[root@LB00 Day01]# . test.sh 
Hello World

其他shell执行方式:
[root@LB00 Day01]# cat test.sh |bash
Hello World
[root@LB00 Day01]# bash < test.sh 
Hello World

变量

一、变量的含义

用一个固定不变的值来代替经常变化的值称为变量!
x=1 y=x+1 y=2
类似书本的目录: 目录存放着具体内容

二、变量的分类

环境变量(全局变量) 对于系统所有的bash生效 默认系统定义好的 都是大写
普通变量(局部变量) 自己来定义的变量 一般都在脚本文件中定义
全局变量先生效,局部变量后生效,所以全局变量与局部变量重复时候,最终局部变量生效

按照生成周期分类:
临时变量: 直接在当前shell中定义的变量 重启或者重新连接失效 name=koten
永久变量: 写入到/etc/profile(每次xshell连接都会执行里面的变量)

定义变量的两种书写方式:
变量名称=变量的值         只在当前的shell中生效
export 变量名称=变量的值  在所有的shell中生效,但是其他连接的会话不会生效

c4244a2647c74b259ff0cb778b8acdaf.png

三、变量相关的配置文件

全局生效 
[root@lb day01]# ll /etc/profile
-rw-r--r-- 1 root root 1819 May 12 12:10 /etc/profile
用户变量文件:
~/.bashrc
~/.bash_profile
/etc/bashrc

shell环境变量相关配置文件的优先级是(执行顺序同)
/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc

四、变量定义方式 

语法:
    变量名称=变量的值
变量名称的定义方式: 字母 数字 下划线组合,以字母或者下划线开头,不能以数字开头,等号两端不允许有空格

变量名称的书写方式: 见名知其意
第一种: 全大写 NAME_AGE 系统默认都是大写的
第二种: 全小写 name_age
第三种: 首字母大写 大驼峰语法  Name_Age
第四种:首字母大写,但是首单词不大写 小驼峰语法 name_Age

变量值的定义:

第一种: 数字的定义,连续的数字,不连续的使用引号引起来
[root@LB00 ~]# age=123
[root@LB00 ~]# age=12 3
-bash: 3: command not found
[root@LB00 ~]# age='12 3'
[root@LB00 ~]# echo $age
12 3

第二种: 字符串定义,连续的字符串
[root@LB00 ~]# name=ko ten    #字符串
-bash: ten: command not found
[root@LB00 ~]# name='ko ten'
[root@LB00 ~]# echo $name
ko ten
[root@LB00 ~]# dir=/etc/sysconfig/network-scripts/ifcfg-eth0    #文件路径
[root@LB00 ~]# echo $dir
/etc/sysconfig/network-scripts/ifcfg-eth0
[root@LB00 ~]# cat $dir
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.4
PREFIX=24
GATEWAY=10.0.0.2
DNS1=223.5.5.5
[root@LB00 ~]# dir=/server/scripts/    #目录路径
[root@LB00 ~]# cd $dir
[root@LB00 scripts]# cd
[root@LB00 ~]# tar zcvf all.tar.gz $dir
tar: Removing leading `/' from member names
/server/scripts/
/server/scripts/Day01/
/server/scripts/Day01/test.sh

第三种定义方式: 命令的定义
[root@LB00 ~]# test=`pwd`    #命令执行后将执行结果发送给变量,而不是每调用一次就执行一次
[root@LB00 ~]# echo $test
/root
[root@LB00 ~]# cd /
[root@LB00 /]# echo $test
/root
[root@LB00 ~]# test='pwd'    #将命令赋值给变量
[root@LB00 ~]# echo $test
pwd
[root@LB00 ~]# $test         #这个才是执行变量
/root
[root@LB00 ~]# cd /
[root@LB00 /]# $test
/
下面同理,注意是想命令执行后给变量还是把命令给变量
[root@LB00 /]# test=`date +%F-%H-%M-%S`
[root@LB00 /]# echo $test
2023-05-12-18-22-11
[root@LB00 /]# echo $test
2023-05-12-18-22-11
[root@LB00 /]# test='date +%F-%H-%M-%S'
[root@LB00 /]# echo $test
date +%F-%H-%M-%S
[root@LB00 /]# $test
2023-05-12-18-22-57
[root@LB00 /]# $test
2023-05-12-18-22-58

还有一个进阶用法,一般在脚本内部使用,命令行不使用这个,就是变量如果没有被定义,会有默认值

[root@Master231 ~]# cat name.sh
NAME=${1:-koten}
echo $NAME
[root@Master231 ~]# sh name.sh 
koten
[root@Master231 ~]# sh name.sh boss
boss

五、Shell重要的位置变量

5.Shell重要的位置变量

$0 表示脚本的名称
[root@LB00 Day01]# cat test.sh
#!/bin/bash
echo $0
[root@LB00 Day01]# sh test.sh
test.sh

使用场景:
[root@LB00 Day01]# cat test.sh
#!/bin/bash
echo "Usage: $0 {start|stop|status|restart|force-reload}"
[root@LB00 Day01]# sh test.sh 
Usage: test.sh {start|stop|status|restart|force-reload}
[root@LB00 Day01]# /server/scripts/Day01/test.sh 
Usage: /server/scripts/Day01/test.sh {start|stop|status|restart|force-reload}

$n  n为数字 表示脚本的第n个参数 0被名称占用 所以从1开始
$1 为脚本第一个参数 $2 为脚本的第二个参数
[root@LB00 Day01]# cat test.sh
#!/bin/bash
echo $1 $2
[root@LB00 Day01]# sh test.sh name 20
name 20
[root@LB00 Day01]# cat test.sh
#!/bin/bash
echo $1 $2 ${10} ${11}
[root@LB00 Day01]# sh test.sh {a..z}
a b j k

$#  表示脚本传参的个数
[root@LB00 Day01]# cat test.sh
#!/bin/bash
echo $#
[root@LB00 Day01]# sh test.sh {a..z}
26
使用场景: 控制用户传参的个数
[root@LB00 Day01]# cat test.sh
#!/bin/bash
if [ $# -ne 2 ]
then
  echo "必须输入两个参数"
  exit
fi
echo $1+$2|bc
[root@LB00 Day01]# sh test.sh 1 1
2

$?  表示上一条命令的执行结果 0为成功 非0失败
使用场景:
[root@LB00 Day01]# cat install.sh
#!/bin/bash
yum -y install wget &> /dev/null
[ $? -eq 0 ] && echo "wget安装成功" || echo "安装失败"
[root@LB00 Day01]# sh install.sh 
wget安装成功

[root@LB00 Day01]# cat ping.sh
#!/bin/bash
ping -c1 -W1 $1 &>/dev/null
[ $? -eq 0 ] && echo "$1 ping的通" || "$1 ping不通"
[root@LB00 Day01]# sh ping.sh www.baidu.com
www.baidu.com ping的通

$$  表示脚本的PID
[root@LB00 Day01]# cat test.sh    
#!/bin/bash
echo $$ > /tmp/nginx.pid    #方便到时候删除

$*  获取脚本的所有参数 在循环体中加双引号把所有的参数作为一个参数  
[root@LB00 Day01]# set -- "a b" c
[root@LB00 Day01]# echo $*
a b c
[root@LB00 Day01]# for i in $*;do echo $i;done
a
b
c
[root@LB00 Day01]# for i in "$*";do echo $i;done
a b c

$@  获取脚本的所有参数 在循环体中加上引号把所有的参数作为独立的参数
[root@LB00 Day01]# for i in "$@";do echo $i;done
a b
c

$_  表示获取执行脚本最后的一个值 类似esc .


-----重要
$0 表示脚本名称
$n 表示脚本传参的第n个参数
$# 表示传参的个数
$? 表示上一条命令的执行结果

------了解
$$    脚本pid
$!    表示上一个后台任务(即通过&符号向后台提交的进程)的进程ID
$*    获取脚本的所有参数,在循环体中加双引号,把所有参数作为一个参数整体
$@    获取脚本的所有参数,在循环体中加双引号,所有参数都是独立的参数
$_    脚本中上一条命令的最后的参数,类似于esc .

六、变量三种传参方式 

第一种: 直接传参
[root@LB00 Day01]# cat test.sh
#!/bin/bash
echo name: $1
echo age: $2
[root@LB00 Day01]# sh test.sh koten 20
name: koten
age: 20

第二种: 赋值传参
[root@LB00 Day01]# cat test.sh
#!/bin/bash
name=$1
age=$2
echo name: $name
echo age: $age
[root@LB00 Day01]# sh test.sh koten 20
name: koten
age: 20

第三种: read读入,交互式
[root@LB00 Day01]# cat test.sh 
#!/bin/bash
read -p "请您输入姓名:" name
read -p "请您输入年龄:" age  
echo 姓名: $name
echo 年龄: $age
[root@LB00 Day01]# sh test.sh
请您输入姓名:koten
请您输入年龄:20  
姓名: koten
年龄: 20

扩展

需求:使用三种传参方式,修改主机名称和IP地址,修改完IP,输出修改的结果到屏幕,在重启网络

一、直接传参

[root@LB00 Day01]# cat change.sh
#!/bin/bash
hostnamectl set-hostname --static $1
sed -i 's#IPADDR.*#IPADDR='$2'#g' /etc/sysconfig/network-scripts/ifcfg-eth0
systemctl restart network
[root@LB00 Day01]# sh change.sh LB00 10.0.0.4
[root@LB00 Day01]# hostname
LB00
[root@LB00 Day01]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.0.0.4
PREFIX=24
GATEWAY=10.0.0.2
DNS1=223.5.5.5

二、赋值传参

[root@LB00 Day01]# cat change.sh
#!/bin/bash
hostname=$1
ip=$2
hostnamectl set-hostname --static $hostname
sed -i 's#IPADDR.*#IPADDR='$ip'#g' /etc/sysconfig/network-scripts/ifcfg-eth0
systemctl restart network

三、read交互式传参

[root@LB00 Day01]# cat change.sh 
#!/bin/bash
read -p "请输入要修改的主机名:" hostname
read -p "请输入要修改的ip:" ip
hostnamectl set-hostname --static $hostname
sed -i 's#IPADDR.*#IPADDR='$ip'#g' /etc/sysconfig/network-scripts/ifcfg-eth0
systemctl restart network
[root@LB00 Day01]# sh change.sh 
请输入要修改的主机名:LB0
请输入要修改的ip:10.0.0.3

#因为修改了ip,Xshell断开了

19a1e94072be4e0699a567d9c6e5be96.png


我是koten,10年运维经验,持续分享运维干货,感谢大家的阅读和关注!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为了实现自动化运维,可以编写shell脚本来调用SQL语句,以下是一个简单的例子: ```shell #!/bin/bash # 定义变量 MYSQL_USER="root" MYSQL_PASSWORD="password" MYSQL_HOST="localhost" MYSQL_PORT="3306" MYSQL_DATABASE="test" # 执行SQL语句 mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -h${MYSQL_HOST} -P${MYSQL_PORT} -D${MYSQL_DATABASE} -e "SELECT * FROM users;" # 执行完毕 echo "SQL query executed successfully." ``` 在这个例子中,我们定义了MySQL的用户名、密码、主机、端口和数据库名等变量,并使用`mysql`命令执行了一个简单的SQL查询语句。你可以根据自己的需求修改这个脚本,例如添加备份和恢复功能等。 另外,为了实现自动化运维,你还可以编写shell脚本来定期执行一些任务,例如清理缓存、备份数据库等。以下是一个简单的例子: ```shell #!/bin/bash # 定义变量 MEMORY_THRESHOLD=70 LOG_FILE="/var/log/freeMemoryLog.txt" # 检查内存使用率 MEMORY_USAGE=$(free | awk '/Mem/{printf("%.2f"), $3/$2*100}') # 如果内存使用率过阈值,则释放缓存 if [ $(echo "${MEMORY_USAGE} > ${MEMORY_THRESHOLD}" | bc -l) -eq 1 ]; then sync && echo 3 > /proc/sys/vm/drop_caches echo "$(date) - Memory usage is ${MEMORY_USAGE}%, cache cleared." >> ${LOG_FILE} else echo "$(date) - Memory usage is ${MEMORY_USAGE}%, no action taken." >> ${LOG_FILE} fi # 执行完毕 echo "Script executed successfully." ``` 在这个例子中,我们定义了一个内存使用率的阈值和日志文件的路径,并使用`free`命令检查当前内存使用率。如果内存使用率过阈值,则使用`sync`命令同步缓存并使用`echo`命令将3写入`/proc/sys/vm/drop_caches`文件中以释放缓存。最后,我们将执行结果写入日志文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是koten

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值