Day...1
大纲
基础变量 bash
shell执行方式 if判断 for循环 while循环 until循环
条件控制语句 exit continue break 函数 数组
1.Shell可以做什么?
1)安装操作系统 CentOS6.X 、CentOS7.X 手动方式安装 克隆方式
自动化安装、cobbler、kickstart 底层都是shell脚本实现
2)shell脚本可以优化
优化SSH、关闭Selinux、优化防火墙(Firewalld)、放行Nginx(80)、HTTPS(443)、SSH端口、zabbix监控(10051)数据库Mysql仅本地连接(127.0.0.1)、企业与个人需求放行的端口、加大文件描述符、时间同步(硬件时间clock、软件时间date)、默认YUM源......
3)安装服务
Nginx、Apache、Tomcat、PHP、MySQL、Redis、Mongo、docker.....
集群中,即有安装PHP5.4又有安装PHP7.1,可以写入shell脚本,自动化安装不同版本的服务
4)代码上线
shell脚本自动化发布、自动化回滚
5)zabbix监控
硬件、软件、进程、端口号、自定义监控......---> shell脚本+定时任务
6)日志分析
日志统计--->三剑客+定时任务+shell脚本
日志展示--->ELK
7)业务层面shell编写业务框架
8)辅助开发程序
python nohup python3.5 test.py & nohup.out 大量的日志,辅助清空
2.Shell用到的基础知识
1)vim编辑器快捷键
2)Linux常用命令,60个左右
3)三剑客 awk sed grep find
4)xshell、Crt 连接工具
3.Shell编程
1)重点掌握的内容 变量、判断、bash
2)看懂、读懂shell脚本
3)判断 前面的脚本进行完善
4)写简单的脚本项目 随机点餐 会员办理服务 会员账号 密码 密码丢失
5)Shell编程或完善的文档
6)Shell编程,解决企业中大部分的shell问题
4.编程语言
Shell、Python、Go、ruby、c、c++、javascript、perl......
编译型语言: 只编译一次,后面直接运行代码即可
解释型语言: 运行一次,解释一次
解释型语言目前不一定比编译型语言慢,优化后,也很快,甚至比编译还快
shell和python区别:
shell 处理系统底层的内容,程序运行、启动、系统运行--->用于shell脚本实现
python、php主要作用搭建web: 自动化CMDB、处理底层的效率低
5.Shell
Linux中默认的shell是: bash
输入输出传达到bash,bash翻译命令给内核,内核驱动相应的硬件完成工作,完成结果反馈给用户
bash两种工作方式:
交互式: 使用者输入命令,bash执行命令,执行完,使用者退出,bash结束
非交互式: 把命令写入到文件中,bash执行文件中的内容,执行到末尾 bash结束
通过xshell登录到系统中,当前的位置属于父shell,所有的文件在执行时调用子shell执行,执行结束子shell退出
6.Shell脚本
命令的堆积
将命令写入到一个文本中 shell脚本 语法格式 if判断 for循环 while 函数 数组......
7.Shell脚本入门、规范
1)脚本统一存放固定的目录 /server/scripts ,统一化是为自动化铺垫
2)脚本命令结尾以.sh结尾,LINUX中的后缀给自己看,区分文件用
3)shell脚本的开头 写解释器 #!/bin/bash或#!/bin/sh
# sh 为 bash 的软连接 [root@shell:~]# ll /bin/bash -rwxr-xr-x. 1 root root 964536 Apr 1 2020 /bin/bash [root@shell:~]# ll /bin/sh lrwxrwxrwx. 1 root root 4 Aug 26 01:35 /bin/sh -> bash
4)脚本最好有注释、说明 #Author 时间 电话 QQ...
5)说明尽量用英文,最好用中文
6)成对的符号、循环语句一次性书写完毕
8.第一个shell脚本
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo "Hello World!"
执行脚本的三种常用的方式:
注意:子shell生命周期特别短暂,父shell相当于在命令行输入
1.bash或sh方式,通过解释器执行脚本--->在子shell中执行命令
[root@shell /server/scripts]# sh test.sh Hello World! [root@shell /server/scripts]# bash test.sh Hello World!
2.路径方式 全路径或当前路径,必须给x权限,开机自动加载一个shell脚本 /etc/rc.local--->在子shell中执行命令
[root@shell /server/scripts]# chmod +x test.sh [root@shell /server/scripts]# /server/scripts/test.sh Hello World! [root@shell /server/scripts]# ./test.sh Hello World!
3.source或 . 方式--->在父shell中执行命令
[root@shell /server/scripts]# . test.sh Hello World! [root@shell /server/scripts]# source test.sh Hello World!
4.子shell与父shell证明,子shell调用周期特别短暂,调用结束失效,父shell调用时间长
[root@shell ~]# cat 1.sh #!/bin/bash name=majunnan [root@shell ~]# sh 1.sh # 在子shell中执行 [root@shell ~]# echo $name # 显示变量 # 空 [root@shell ~]# source 1.sh # 在父shell中执行 [root@shell ~]# echo $name # 显示变量 majunnan
5.使用其他shell的执行方式
[root@shell /server/scripts]# cat test.sh pwd [root@shell /server/scripts]# cat test.sh|bash /server/scripts [root@shell /server/scripts]# echo ls ls [root@shell /server/scripts]# echo ls|bash test.sh # 读入的方式,把文件中的内容传入到bash中,一行一行读取,一边读取,一边执行 [root@shell /server/scripts]# bash < test.sh /server/scripts
9.shell的变量基础
什么是变量?
用一个固定的字符串表示不固定的值,称为变量
变量的种类: 查看全局变量 env
环境变量(全局变量) 针对全局生效,对所有的shell生效,例:PS1、PATH、LANG
普通变量(局部变量) 针对当前某个shell生效
按照生命周期区分:
永久的: 写入/etc/profile,每次使用xshell连接系统,都会自动加载/etc/profile
临时的: 使用export声明即可
添加export区别: 对当前打开窗口的所有shell生效 (无论父shell、子shell)
不加export区别: 只对当前的shell生效(即使父shell,资源也无法下发)
[root@shell ~]# age=18 # 只对当前父shell有效 [root@shell ~]# echo $age 18 [root@shell ~]# cat 1.sh echo $age [root@shell ~]# sh 1.sh 空 # 只对上面的父shell生效,未对当前子shell生效 [root@shell ~]# export name=nn # 对当前打开的所有窗口生效 [root@shell ~]# echo $name nn [root@shell ~]# cat 2.sh echo $name [root@shell ~]# sh 2.sh nn [root@shell ~]# echo $name # 另开一台xshell窗口,$name未生效 空
案例: rsync -avz hosts rsync_backup@10.0.0.41::backup
10.定义环境变量name=nn
[root@shell ~]# _name=nn [root@shell ~]# echo $_name nn [root@shell ~]# 1name=mm -bash: 1name=mm: command not found
NAME_AGE= 全大写 系统默认的变量都是大写 Name_Age 大驼峰语法 name_Age 小驼峰语法 name_age 全小写
1.字符串定义:必须是连续的字符串,值不允许有空格
双引号和单引号的区别:双引号解析变量,单引号所见即所得,不能解析变量,不加引号可以解析变量
[root@shell ~]# name=majunnan # 连续,不允许有空格 [root@shell ~]# name='I am majunnan' # 使用单引号,允许有空格 [root@shell ~]# echo $name I am majunnan [root@shell ~]# name="I am majunnan" # 使用双引号,允许有空格 [root@shell ~]# echo $name I am majunnan
[root@shell ~]# age="12 23 432" [root@shell ~]# echo $age 12 23 432
[root@shell ~]# date +%F-%H-%M-%S 2021-10-18-15-39-36 [root@shell ~]# time=`date +%F-%H-%M-%S` [root@shell ~]# echo $time 2021-10-18-15-40-03 [root@shell ~]# echo $time # 不会变,time成为定值,调用time的值是固定的 2021-10-18-15-40-03 [root@shell ~]# time=$(date +%F-%H-%M-%S) # $()与``相同 [root@shell ~]# echo $time 2021-10-18-15-43-12
时间是固定,每次调用时间都相同
[root@shell ~]# cat 1.sh #!bin/bash time=`date +%F-%H-%M-%S` echo $time sleep 2 echo $time [root@shell ~]# sh 1.sh 2021-10-18-15-44-45 2021-10-18-15-44-45
[root@shell ~]# cat 1.sh #!bin/bash time='date +%F-%H-%M-%S' echo `$time` sleep 2 echo `$time` [root@shell ~]# sh 1.sh 2022-09-05-14-57-14 2022-09-05-14-57-16
[root@shell ~]# ip=`ifconfig eth0|awk 'NR==2{print $2}'` [root@shell ~]# echo $ip 10.0.0.7 [root@shell ~]# dir=$ip_$time [root@shell ~]# echo $dir 2021-10-18-15-43-53 # IP没有,没办法分辨IP与时间 [root@shell ~]# dir=${ip}_${time} # 使用{}分开两个变量 [root@shell ~]# echo $dir 10.0.0.7_2021-10-18-15-43-53 [root@shell ~]# mkdir $dir [root@shell ~]# ll total 4 drwxr-xr-x 2 root root 6 Oct 18 15:50 10.0.0.7_2021-10-18-15-43-53
当shell脚本中出现2条以上相同的命令,写成变量
11.核心位置变量
$0 获取shell脚本的名称,执行如果带全路径,则$0带全路径*****
$n n为数字,从1开始,$1为脚本的第一个参数,从$9往后,需要加${10} *****
$# 获取脚本传参的总个数,针对传入的个数进行判断*****
$* 获取脚本传参的所有的参数,在循环体中不同,加上双引号视为单个字符串
$@ 获取脚本传参的所有的参数,在循环体中不同,加上双引号视为独立参数
$? 获取上一条命令的返回值,0为成功,非0失败*****
$$ 获取脚本的PID进程号,当有多个相同名称的shell环境中使用**
$! 获取上一个在后台运行脚本的PID号,测试常用**
$_ 获取脚本的最后一个参数或是某个东西 类似esc .
$0:获取shell脚本名称
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo $0 [root@shell /server/scripts]# sh test.sh test.sh [root@shell /server/scripts]# /server/scripts/test.sh /server/scripts/test.sh # 让脚本给予提示,如何使用脚本 [root@shell /server/scripts]# cat test.sh #!/bin/bash echo $0 echo $"Usage: $0 {start|stop|status|restart|force-reload}"
$0在Linux脚本中的使用方法:
[root@shell /server/scripts]# /etc/init.d/network Usage: /etc/init.d/network {start|stop|status|restart|force-reload}
# 过滤$0,使用撬棍转译或单引号所见即所得,不让他代表特殊含义 [root@shell /server/scripts]# grep \$0 /etc/init.d/network $0 stop $0 start echo $"Usage: $0 {start|stop|status|restart|force-reload}" [root@shell /server/scripts]# grep '$0' /etc/init.d/network $0 stop $0 start echo $"Usage: $0 {start|stop|status|restart|force-reload}"
basename 只获取脚本的名称
[root@shell /server/scripts]# basename /server/scripts/test.sh test.sh
$n 脚本的参数:
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo $1 [root@shell /server/scripts]# sh test.sh mm mm [root@shell /server/scripts]# sh test.sh mm jj nn mm
序列传参:从$9往后,需要加${10}
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo $3 [root@shell /server/scripts]# sh test.sh {A..Z} C [root@shell /server/scripts]# sh test.sh {1..10} 3 [root@shell /server/scripts]# cat test.sh #!/bin/bash echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 [root@shell /server/scripts]# sh test.sh {a..z} a b c d e f g h i a0 a1 # 出现错误,只能识别$1 [root@shell /server/scripts]# cat test.sh # 加上{},使10、11成为一体 #!/bin/bash echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} [root@shell /server/scripts]# sh test.sh {a..z} a b c d e f g h i j k
$#获取脚本传参的总个数:
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} echo $# [root@shell /server/scripts]# sh test.sh a b c a b c 3 [root@shell /server/scripts]# sh test.sh {a..z} a b c d e f g h i j k 26 [root@shell /server/scripts]# sh test.sh {1..10000} 1 2 3 4 5 6 7 8 9 10 11 10000
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo name=$1 echo age=$2 [root@shell /server/scripts]# sh test.sh mm 18 name=mm # 此时显示mm只是代表字符串,未对name进行赋值 age=18 # 此时显示18也只是代表字符串,未对age进行赋值
[root@shell ~]# [ 10 -eq 10 ] # 10等于10 [root@shell ~]# echo $? # 查看运行的结果,如果结果返回等于0,则上一条运行结果成立 0 [root@shell ~]# [ 10 -ne 10 ] # 10不等于10 [root@shell ~]# echo $? # 查看运行的结果,如果结果返回不等于0,则上一条运行结果不成立 1 [root@shell /server/scripts]# cat test.sh #!/bin/bash [ $# -ne 2 ] && echo "请输入两个参数" && exit # 参数总个数不为2,输出文字并退出 echo name=$1 echo age=$2 [root@shell /server/scripts]# sh test.sh test # 输入一个参数时,输出文字,退出 请输入两个参数 [root@shell /server/scripts]# sh test.sh test 18 name=test age=18
$* $@:获取脚本传参的所有参数
[root@shell /server/scripts]# cat test.sh name=$1 age=$2 $* $@ [root@shell /server/scripts]# sh test.sh {1..10} name=1 age=2 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 [root@shell /server/scripts]# sh test.sh {a..z} name=a age=b a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z
测试$* $@在循环体中加双引号区别
[root@shell /server/scripts]# set -- "I am" majunnan # 设置变量 [root@shell /server/scripts]# echo $* I am majunnan [root@shell /server/scripts]# echo $@ I am majunnan [root@shell /server/scripts]# echo "$@" I am majunnan [root@shell /server/scripts]# echo "$*" I am majunnan [root@shell /server/scripts]# for i in $*;do echo $i;done I am majunnan [root@shell /server/scripts]# for i in $@;do echo $i;done I am majunnan [root@shell /server/scripts]# for i in "$*";do echo $i;done I am majunnan # 加双引号,视为单个字符串 [root@shell /server/scripts]# for i in "$@";do echo $i;done I am # 加双引号,视为独立个体 majunnan
$?:获取上一条命令的返回值
[root@shell /server/scripts]# ll [root@shell /server/scripts]# echo $? 0 [root@shell /server/scripts]# llllllllllllll bash: llllllllllllll: command not found [root@shell /server/scripts]# echo $? 127 [root@shell ~]# ping -c1 -W1 www.baidu.com &>/dev/null [root@shell ~]# echo $? 0 [root@shell ~]# cat ping.sh #!/bin/bash ping -c1 -W1 $1 &>/dev/null [ $? -eq 0 ] && echo "$1 通的" || echo "$1 不通" [root@shell ~]# sh ping.sh www.baidu.com www.baidu.com 通的 [root@shell ~]# sh ping.sh www.baidu.commmmmm www.baidu.commmmmm 不通 [root@shell ~]# sh ping.sh 10.0.0.5 10.0.0.5 不通 [root@shell ~]# sh ping.sh 10.0.0.1 10.0.0.1 通的
$$ 获取脚本的PID进程号,当有多个相同名称的shell环境中使用
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo $$ # 显示当前进程PID,当多人登录使用一个服务时,可知自己进程PID [root@shell /server/scripts]# cat test.sh #!/bin/bash echo $$ > /tmp/nginx_pid # 将当前的PID号写入文本中,可查看确定自己使用的服务
$! 获取上一个在后台运行脚本的PID号,测试常用**
[root@shell ~]# cat test.sh #!/bin/bash echo $$ > /tmp/nginx_pid [root@shell ~]# sh test.sh [root@shell ~]# kill -9 $! kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
$_ 获取脚本的最后一个参数或是某个东西 类似esc .
[root@shell ~]# ll 1234567 89 10 ls: cannot access 1234567: No such file or directory ls: cannot access 89: No such file or directory ls: cannot access 10: No such file or directory [root@shell ~]# echo $_ # 上一行输入最后一个是10,所以取10 10
12.脚本传参的三种方式
第一种方式:直接传参
[root@shell /server/scripts]# cat test.sh #!/bin/bash echo $1 $2 [root@shell /server/scripts]# sh test.sh mm 100 mm 100
第二种方式:赋值传参
[root@shell /server/scripts]# cat test.sh #!/bin/bash name=$1 age=$2 echo $name echo $age [root@shell /server/scripts]# sh test.sh mm 200 mm 200 [root@shell /server/scripts]# cat test.sh #!/bin/bash name=$1 age=$2 echo 姓名: $name echo 年龄: $age [root@shell /server/scripts]# sh test.sh nn 100 姓名: nn 年龄: 100
第三种方式:read读入,交互式
[root@shell /server/scripts]# read name nn # 写入nn [root@shell /server/scripts]# echo $name nn # 出现nn [root@shell /server/scripts]# read -p "请输入你的姓名" name 请输入你的姓名nn # 写入nn [root@shell /server/scripts]# echo $name nn # 出现nn [root@shell /server/scripts]# read -p "请输入你的姓名: " name 请输入你的姓名: HEHE # 写入HEHE [root@shell /server/scripts]# echo $name HEHE # 出现HEHE
read第一种书写方式:一个一个
[root@shell /server/scripts]# cat test.sh #!/bin/bash read -p "请输入你的姓名: " name read -p "请输入你的年龄: " age echo name=$name echo age=$age [root@shell /server/scripts]# sh test.sh 请输入你的姓名: hehe # 书写 请输入你的年龄: 1 # 书写 name=hehe # 显示 age=1 # 显示
read第二种书写方式:一起
[root@shell /server/scripts]# cat test.sh #!/bin/bash read -p "请输入你的姓名和年龄: " name age echo name=$name echo age=$age [root@shell /server/scripts]# sh test.sh 请输入你的姓名和年龄: nn 20 # 书写 name=nn # 显示 age=20 # 显示 [root@shell /server/scripts]# cat test.sh #!/bin/bash read -p "输入要备份的目录: " dir tar zcf test.tar.gz $dir [root@shell /server/scripts]# sh test.sh 输入要备份的目录: /etc [root@shell /server/scripts]# ll -rw-r--r-- 1 root root 86 Jul 20 20:23 test.sh -rw-r--r-- 1 root root 11571902 Jul 20 20:23 test.tar.gz
13.小结
1.学习shell
2.基础知识
3.规范
4.语言种类
5.shell执行的三种方式
6.变量分类 export区别 变量相关的文件
7.变量的定义 名字定义 值的定义 命令的定义
8.核心位置变量 $0 $n $# $?
9.传参的三种方式 直接传参 赋值传参 read读入
——————————————————————————————————————————————————————————————————————————
无敌小马爱学习