shell学习目标

1. Shell基本概述2. Shell的变量定义3. Shell数值运算4. Shell的流程控制  if语句5. Shell的循环语句 for  while循环6. Shell的数组函数7. Shell内置命令 8. Shell正则表达式  Awk Grep Sed

Shell

shell概述

1、shell是命令解释器,shell存在Linux系统的最外层,shell连接系统,负责和用户对话,用户输入用户名和密码登陆后的所有输入都由shell解释并执行。2、shell存在交互式和非交互式
2.1 交互式
#比如,我们用命令 “echo $-” 问 shell 你都有什么功能啊?
[root@shell01 ~]# echo $-
himBH
#shell回答,我有 “himBH” 这些功能
01)h:hashall,打开这个选项后,Shell会将命令所在的路径记录下来,避免每次都要查询。
02)i:interactive,包含这个选项说明当前的Shell是一个交互式的Shell。
03)m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等。
04)B:braceexpand,大括号扩展。
05)H:history,Shell会把我们执行的命令记录下来,可以通过history命令查看。
2.2 非交互式,我们把命令 “echo $-” 放到脚本中执行,就是非交互式的
[root@shell01 ~]# vim test.sh
#!/bin/bash
echo $-
[root@shell01 ~]# sh test.sh
hB
#shell脚本执行结果只有 “hB”3、shell的作用:减少重复性工作,提高工作效率,实现自动化运维。4、shell脚本能做什么:
01)基础配置:系统初始化操作、系统更新、内核调整、网络、时区、SSH优化等。
02)安装程序:LNMP、LAMP、MySQL、Nginx、Redis等。
03)配置变更:Nginx Conf、PHP Conf、MySQL Conf、Redis Conf等。
04)业务部署:Shell配合Git、Jenkins实现自动化部署PHP、Java代码,以及代码回滚。
05)日常备份:MySQL全备 + 增量 + binlog + crond + Shell脚本备份等。
06)信息采集:Zabbix + Shell: 对硬件、系统、服务、网络的监控等。
07)日志分析:ELK:取值->排序->去重->统计->分析等。
08)服务扩容/缩容:Zabbix + Shell扩容: 监控服务器cpu, 如cpu负载持续80% + 触发动作(脚本)脚本: 调用api开通云主机->初始化环境->加入集群->对外提供访问缩容: 监控服务器cpu使用率20%->判断有多少web节点->判断是否超过预设->缩减到对应的预设状态->变更负载的配置

Shell脚本编写规范

注意:#!/bin/bash 这一行必须在每个脚本顶端的第一行,如果不是第一行则为脚本注释行。
01)以 #!/bin/bash 或 #!/bin/sh 开头,开头的"#!"称为幻数,如不指定Shell,默认以bash执行,在执行Shell脚本的时候,内核会根据"#!"后的解释器来确定使用哪个程序解释脚本中的内容。
02)建立一个目录作为脚本的统一存放位置 mkdir scripts
03)用vim编辑器进行脚本编辑,有不同的颜色高亮显示,便于观察
04)脚本名称要以 .sh 结尾,便于使用
05)建议脚本中写上注释行,用来注明脚本中命令行的作用,建议用英文编写
06)编写脚本时,成对的符号一定要一次写完,再写符号内的内容,循环格式一次性写完
07)在需要退出的地方可以增加 exit 命令退出脚本
#!/bin/bash
if [[ 满足条件1 ]]; then执行这里的命令
elif [[ 满足条件2 ]]; then执行这里的命令
elseexit #主动退出脚本,不再执行后面的脚本内容
fi

Shell的执行方式

脚本从上到下 从左到到右的方式进行执行,脚本执行时遇到子脚本,会执行子脚本,子脚本执行完成后,退出子脚本,继续执行脚本中的内容。脚本运行时,会向系统内核请求一个进程。脚本就会在该进程下进行运行,终止操作。#创建一个脚本
[root@shell01 /scripts]# echo "pwd"  >test.sh
[root@shell01 /scripts]# cat test.sh
pwd
[root@shell01 /scripts]# ll
total 4
-rw-r--r-- 1 root root 4 2020-02-19 11:10 test.sh#脚本执行方法
#必须要有执行权限
1、path/script-name(绝对路径)  或者  ./script-name
[root@shell01 /scripts]# chmod u+x test.sh
[root@shell01 /scripts]# ll
total 4
-rwxr--r-- 1 root root 4 2020-02-19 11:10 test.sh
[root@shell01 /scripts]# /scripts/test.sh
/scripts
[root@shell01 /scripts]# ./test.sh
/scripts#不需要执行权限
#脚本运行时,会向系统内核请求一个进程。脚本就会在该进程下进行运行。
1. bash script-name  或者  sh script-name
[root@shell01 /scripts]# bash  test.sh
/scripts
[root@shell01 /scripts]# sh  test.sh
/scripts#无需执行权限,将脚本中的命令调入到当前环境下执行,这种情况下脚本中的语法并不全部适合当前的命令行语法规范,会出现错误提示,不建议使用.
3. source  script-name  或者  . script-name
4. cat script-name  | bash
5. bash  < script-name

shell变量

1、变量定义

#一般定义变量用大写字母,如果有2个相邻的变量,建议用空格或花括号隔开
[root@dev01 ~]# echo $a $b
1 2
[root@dev01 ~]# echo ${a}$b
12#定义单个变量
[root@dev01 ~]# a=1               #为变量 a 赋值
[root@dev01 ~]# b=2               #为变量 b 赋值
[root@dev01 ~]# echo $a_$b     #不加引号:中间如果是+-*/@#%^&或者空格都可以显示出2个变量内容
2
[root@dev01 ~]# echo '$a'_$b #单引号:强引用,里面是什么,就输出什么
$a_2
[root@dev01 ~]# echo "$a"_$b #双引号:弱引用,吃什么吐什么,会解析变量
1_2
[root@dev01 ~]# echo `$a`_$b #反引号 ``:优先执行反引号里面的命令 跟  $() 含义一样
-bash: a: command not found
_2#变量内容定义为多个变量
[root@dev01 ~]# c=${a}_$b
[root@dev01 ~]# echo $c
1_2#变量内容定义为命令
[root@dev01 ~]# d=$(pwd)
[root@dev01 ~]# echo $d
/root

2、变量取值

变量 说明
${#变量} 获取变量的长度
${变量#匹配规则} 从头开始匹配,最短删除,第一次匹配到哪里就删除到哪里
${变量##匹配规则} 从头开始匹配,最长删除,最后匹配到哪里就删除到哪里
${变量%匹配规则} 从尾开始匹配,最短删除,第一次匹配到哪里就删除到哪里
${变量%%匹配规则} 从尾开始匹配,最长删除,最后匹配到哪里就删除到哪里
${变量/旧的字符串/新的字符串} 替换变量中的旧的字符串为新的字符串,只替换第一个
${变量//旧的字符串/新的字符串} 替换变量中的旧的字符串为新的字符串,替换所有
${变量:匹配规则:匹配规则} 索引及切片
#变量替换实战
[root@shell /scripts]# url=www.sina.com.cn        #定义变量
[root@shell /scripts]# echo $url               #打印变量
www.sina.com.cn
#取出变量长度
[root@shell /scripts]# echo ${#url}                #获取变量值的长度
15
#从头删除
[root@shell /scripts]# echo ${url#*.}      #从头开始匹配,最短删除,*表示所有,点没有任何含义
sina.com.cn
[root@shell /scripts]# echo ${url##*.}     #从头开始匹配,最长删除
cn
#从尾删除
[root@shell /scripts]# echo ${url%.*}      #从尾开始匹配,最短删除
www.sina.com
[root@shell /scripts]# echo ${url%%.*}     #从尾开始匹配,最长删除
www
#替换
[root@shell /scripts]# echo ${url/w/W}     #将旧的字符串替换为新的字符串,只替换第一个字符串
Www.sina.com.cn
[root@shell /scripts]# echo ${url//w/W}        #将旧的字符串替换为新的字符串,替换所有
WWW.sina.com.cn
[root@shell /scripts]# echo ${url/w/}      #将第一个匹配到w删除
ww.sina.com.cn
[root@shell /scripts]# echo ${url//w/}     #将所有匹配到w删除
.sina.com.cn#索引及切片
[root@shell /scripts]# echo $url               #打印变量
w  w  w  .  s  i  n  a  .  com.cn
0  1  2  3  4  5  6  7  8  9
[root@shell /scripts]# echo ${url:0:3}     #从0列开始匹配,切出3列   0-2列
www
[root@shell /scripts]# echo ${url:5:4}     #从5列开始匹配,切出4列, 5-8
ina.
[root@shell /scripts]# echo ${url:5}       #切除前5列=0-4列删除
ina.com.cn[root@shell /scripts]# cat var-2.sh
#!/bin/bash
#1.定义变量
String='Bigdata process is Hadoop, Hadoop is open source project'
#2.打印变量
echo $String
#3.输出菜单
cat<<EOF
1)打印string长度
2)删除字符串中所有的Hadoop
3)替换第一个Hadoop为Linux
4)替换全部Hadoop为Linux
EOF
#4.提示用户输入对应的数字,执行对应的功能
read -p "请输入上方菜单对应的数字,执行其对应的功能[1|2|3|4]:" Num
#5.根据用户输入的数字进行执行对应的功能
if [ $Num -eq 1 ];thenecho "正在打印变量String的长度....."echo ${#String}
elif [ $Num -eq 2 ];thenecho "正在删除字符串中的所有Hadoop"echo ${String//Hadoop/}
elif [ $Num -eq 3 ];thenecho "正在替换变量中第一个Hadoop为Linux"echo ${String/Hadoop/Linux}
elif [ $Num -eq 4  ];thenecho "正在替换变量中的所有Hadoop为Linux"echo ${String//Hadoop/Linux}
elseecho "你输入的数字不正确!请按照要求输入对应的数字!"
fi

3、变量理论

1、什么是Shell变量?
数据的一种传递方式。  用一个固定的字符串去表示一个不固定的字符串,数值,内容,数据等。2、Shell变量的好处,便于后续调用3、Shell变量的命名规则,建议如下:
Hostname_Ip4、Shell变量定义的方式
4.1. 用户自定义变量,只在当前环境下生效
a=7
a="ni hao"
b='haha o'
Host_ok='good boy'echo "$a $b $Host_ok"
ni hao haha o good boyecho ${a}123 $b
ni hao123 haha oecho $a A $b-B
ni hao A haha o-B#将命令的执行结果赋值给变量
[root@shell01 ~]# Hostname=$(hostname)
[root@shell01 ~]# echo $Hostname
shell01# export 可新增,修改或删除环境变量,供后续执行的程序使用。export 的作用时限仅限于此终端该次登陆操作。
export [-fnp] [变量名称]=[变量值]
-f  代表[变量名称]中为函数名称。
-n  删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
-p  列出所有的shell赋予程序的环境变量,也就是列出本机所有变量,包括自定义变量和系统默认变量
#在命令行定义变量,直接定义和用export定义的区别
[root@shell01 ~]# a=123
[root@shell01 ~]# echo $a
123
[root@shell01 ~]# export -p        #查看本机变量列表,没有刚刚定义的变量a
[root@shell01 ~]# bash
[root@shell01 ~]# echo $a      #执行 bash 后,之前定义的变量a就没有值了[root@shell01 ~]# export b=234
[root@shell01 ~]# export -p        #查看本机变量列表,刚刚定义的变量b的值在列表中
declare -x b="234"
[root@shell01 ~]# bash
[root@shell01 ~]# echo $b      #执行 bash 后,之前定义的变量b的值还有
234
[root@shell01 ~]# export -n b  #删除定义的变量b
#直接定义的变量不可以在脚本中调用,用export定义的变量可以在脚本中调用
#直接定义和用export定义都将在本终端关闭后失效,也不会在其他终端生效4.2. 系统环境变量 系统定义好的,主要是定义系统信息的
/etc/profile  /etc/profile.d/*.sh  /etc/bashrc  ~/.bashrc  ~/.bash_profile
[root@shell01 /scripts]# cat var.sh
#!/bin/bash
echo "当前系统登录的用户为:$USER"
echo "当前所在的目录位置为:$PWD"
echo "当前系统的主机名为:$HOSTNAME"
echo "当前系统用户的家目录为:$HOME"
echo "当前系统登录的用户的UID为:$UID"
echo "当前系统登录的终端IP为:$SSH_CONNECTION"
[root@shell01 /scripts]# sh var.sh
当前系统登录的用户为:root
当前所在的目录位置为:/scripts
当前系统的主机名为:shell01
当前系统用户的家目录为:/root
当前系统登录的用户的UID为:0
当前系统登录的终端IP为:10.0.0.1 63017 10.0.0.7 224.3. 位置参数变量 变量名是固定的,意思也是固定的,通过脚本进行传递数据
#位置变量: $1  $2 .... $9  ${10} ${11}
4.4. 预定义的变量 脚本中已经定义好的,变量名是固定的,作用也是固定的 $-  $?  $$  $@  $*
[root@shell01 /scripts]# cat path.sh
#!/bin/bash
echo "当前shell的脚本名为:$0"
echo "当前shell的第一个位置变量为:$1"
echo "当前shell的第二个位置变量为:$2"
echo "当前shell的第三个位置变量为:$3"
echo "当前shell的所有位置变量为:$*"
echo "当前shell的所有位置变量为:$@"
echo "当前shell的位置变量的个数为:$#"
echo "当前shell脚本的PID号为:$$"
echo "上一条命令的执行结果为:$?"[root@shell01 /scripts]# sh /scripts/path.sh  nginx  php  mysql
当前shell的脚本名为:/scripts/path.sh
当前shell的第一个位置变量为:nginx
当前shell的第二个位置变量为:php
当前shell的第三个位置变量为:mysql
当前shell的所有位置变量为:nginx php mysql
当前shell的所有位置变量为:nginx php mysql
当前shell的位置变量的个数为:3
当前shell脚本的PID号为:8994
上一条命令的执行结果为:0$* $@ 的区别
$*   把参数作为一个整体字符串返回
$@   把参数一个一个进行返回[root@shell01 /scripts]# cat test.sh
#!/bin/bash
test() {echo "未加引号时对比"echo $* echo $@echo "加入引号之后对比"for i in "$*"doecho $idoneecho "###################"for j in "$@"doecho $jdone
}
test nginx  php  mysql  ansible[root@shell01 /scripts]# sh test.sh
未加引号时对比
nginx php mysql ansible
nginx php mysql ansible
加入引号之后对比
nginx php mysql ansible
###################
nginx
php
mysql
ansible

4、变量赋值

read 进行赋值
1. shell脚本中 read 示例语法
[root@shell01 /scripts]# cat read-1.sh
#!/bin/bash
a=11
export b=22
echo $a,$b
read -p "请输入一个值:" Var
echo "你输入的变量值为:$Var "
[root@shell01 /scripts]# sh  read-1.sh
11,22
请输入一个值:oldboy
你输入的变量值为:oldboy2、测试用户输入的IP地址是否能通
根据用户输入的IP地址进行测试  ping -c1 -W1  10.0.0.2
根据测试的结果,返回给用户,通的就返回通,不通就返回不通ping -c1 -W1  10.0.0.2-c 发送几个数据包-W 几秒内返回数据包有效-i 发送每个数据包之间等待的间隔(单位秒)默认设置是等待一秒-s 指定要发送的数据字节数。默认56,当与8字节的ICMP头数据组合时,转换为64个ICMP数据字节。-I 将源地址设置为指定的接口地址。参数可以是数字IP地址或设备名称。在ping IPv6 linklocal地址时,此选项是必需的。-l 如果指定了preload,则ping发送许多不等待回复的数据包。只有超级用户可以选择超过3的预加载-q 静默输出。除启动和完成时的摘要行外,不显示任何内容-r 绕过正常的路由表并直接发送到连接接口上的主机。如果主机不在直接连接的网络上,则返回错误。如果还是用了-I选项,则此选项可用于通过没有路由的接口ping本地主机。-R 记录线路。包含ECHO_REQUEST数据包中的RECORD_ROUTE选项,并在返回的数据包上显示路由缓冲区。请注意,IP报头只能容纳9个这样的路由。许多主机忽略或放弃此选项-t ttl 设置IP生存时间值(TTL)-v 详细输出#方法一
#!/bin/bash
#1.提示用户输入一个IP地址
read -p "请输入一个IP地址进行测试连通情况:" Ip
#2.根据用户输入的IP地址进行测试,将测试结果返回给用户
ping -c1 -W1 $Ip  &>/dev/null && echo "该IP地址$Ip 是通畅的!" || echo "该IP地址$Ip 是不通的!"#方法二
#!/bin/bash
#1.提示用户输入一个IP地址
read -p "请输入一个IP地址进行测试连通情况:" Ip
#2.根据用户输入的IP地址进行测试
ping -c1 -W1 $Ip  &>/dev/null
#3.根据测试结果返回给用户
if [ $? -eq 0 ];thenecho -e "\033[32m该IP地址 $Ip 是通畅的! \033[0m"
elseecho -e "\033[31m该IP地址 $Ip 是不通的! \033[0m"
fiecho命令的特性:输出颜色echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"
echo -e "\e[37m 白色字 \e[0m"echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;37m 红底白字 \033[0m"
echo -e "\033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[0m"
echo -e "\033[44;37m 蓝底白字 \033[0m"
echo -e "\033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[0m"
echo -e "\033[47;30m 白底黑字 \033[0m"echo -e "\e[31m 红色字 \e[32m" 绿色字红色字  绿色字分析:
echo    命令
-e      选项,使用转义字符
" "       弱引用
\e[ m   指定颜色的特殊写法
\e[0m   指定后面的字符都是默认的黑底白字
\033[ m 指定颜色的特殊写法
\033[0m 指定后面的字符都是默认的黑底白字
m       m 前面填写代表颜色的数字,后面填写要显示的内容
30-37   每种数字代表一种字体颜色
40-47   每种数字代表一种底色
#同时使用字体颜色和底色中间用 ; 隔开 字体颜色和底色的数字前后位置都可以 30;47 或者 47;30

5、系统变量

# 系统环境变量 系统定义好的,主要是定义系统信息的,在下面这些文件中定义
/etc/profile  /etc/profile.d/*.sh  /etc/bashrc  ~/.bashrc  ~/.bash_profileexport -p #查看当前登陆窗口所有系统变量echo "当前系统登录的用户为:$USER"
echo "当前所在的目录位置为:$PWD"
echo "当前系统的主机名为:$HOSTNAME"
echo "当前系统用户的家目录为:$HOME"
echo "当前系统登录的用户的UID为:$UID"
echo "当前系统登录的终端IP为:$SSH_CONNECTION"
当前系统登录的用户为:root
当前所在的目录位置为:/scripts
当前系统的主机名为:shell01
当前系统用户的家目录为:/root
当前系统登录的用户的UID为:0
当前系统登录的终端IP为:10.0.0.1 63017 10.0.0.7 22
#位置参数变量 变量名是固定的,意思也是固定的,通过脚本进行传递数据
#位置变量: $1  $2 .... $9  ${10} ${11}
echo "当前shell的脚本名为:$0"
echo "当前shell的第一个位置变量为:$1"
echo "当前shell的第二个位置变量为:$2"
echo "当前shell的第13个位置变量为:${13}"
echo "当前shell的所有位置变量为:$*"
echo "当前shell的所有位置变量为:$@"
echo "当前shell的位置变量的个数为:$#"
echo "当前shell脚本的PID号为:$$"
echo "上一条命令的执行结果为:$?"
[root@shell01 /scripts]# sh /scripts/path.sh  nginx  php ...... mysql
当前shell的脚本名为:/scripts/path.sh
当前shell的第一个位置变量为:nginx
当前shell的第二个位置变量为:php
...... 假设中间有10个字符串单词
当前shell的第13个位置变量为:mysql
当前shell的所有位置变量为:nginx php mysql
当前shell的所有位置变量为:nginx php mysql
当前shell的位置变量的个数为:3
当前shell脚本的PID号为:8994
上一条命令的执行结果为:0$#      传递到脚本的参数的数量
$*      以一个单字符串显示所有向脚本传递的参数,与位置变量不同,此选项参数可超过9个
$$      脚本运行的当前进程ID号
$!      后台运行的最后一个进程的进程ID号
$@     但是使用时加引号,并在引号中返回每个参数
$-      显示shell使用的当前选项,与set命令功能相同
$?      显示最后命令的退出状态。0表示没有错误,其它任何值表明有错误$* $@ 的区别
$*   把参数作为一个整体字符串返回
$@   把参数一个一个进行返回[root@shell01 /scripts]# cat test.sh
#!/bin/bash
test() {echo "未加引号时对比"echo $* echo $@echo "加入引号之后对比"for i in "$*"doecho $idoneecho "###################"for j in "$@"doecho $jdone
}
test nginx  php  mysql  ansible[root@shell01 /scripts]# sh test.sh
未加引号时对比
nginx php mysql ansible
nginx php mysql ansible
加入引号之后对比
nginx php mysql ansible
###################
nginx
php
mysql
ansible

6、变量实战

1、修改主机名
思路:
1.1、提示用户输入新的主机名
1.2、提示用户是否确认修改主机名
1.3、修改主机名
1.4、根据修改的结果进行判断
1.5、修改成功之后,让其立即生效
[root@oldboy /scripts]# cat read-5.sh
#!/bin/bash
#1.提示用户输入新的主机名
read -p "请输入你要修改之后的主机名:" Hostname
#2. 提示用户是否确认修改主机名
read -p "请确认是否真正的修改主机名[yes|no]:" Qr
#3. 根据用户的输入进行是否修改主机名
if [ "$Qr" == "yes" ];thenecho "你选择了修改主机名....."hostnamectl set-hostname $Hostname &>/dev/nullif [ $? -eq 0 ];thenecho "主机名修改成功......"bashelseecho "主机名修改失败......"fi
elseecho "你选择了不修改主机名...."echo "程序脚本退出............"
fi
[root@oldboy /scripts]# sh read-5.sh
请输入你要修改之后的主机名:shell
请确认是否真正的修改主机名[yes|no]:no
你选择了不修改主机名....
程序脚本退出............
[root@oldboy /scripts]# sh read-5.sh
请输入你要修改之后的主机名:shell
请确认是否真正的修改主机名[yes|no]:yes
你选择了修改主机名.....
主机名修改成功......
[root@shell scripts]# source  /etc/profile2、修改IP
思路:
2.1、提示用户输入新的IP地址
2.2、提示用户是否真的修改IP地址
2.3、修改IP地址,提示用户IP地址修改成功
2.4、怎么生效,重启网络服务,IP地址修改之后,远程连接会断开
2.5、怎么修改IP地址,10 和 172 网段都要修改
[root@shell /scripts]# cat read-6.sh
#!/bin/bash
#1. 提示用户输入新的IP地址的主机位
read -p "请输入你要修改之后IP地址的主机位数字为:" Host
#2. 提示用户是否确认修改IP地址的主机位
read -p "是否确认修改主机的IP地址[yes|no]:" Qr
#3. 根据用户的输入进行判断是否修改IP地址
if [ "$Qr" == "yes" ];thenecho "你选择了修改主机的IP地址....."sed -ri "s#(^IPADDR.*\.).*#\1$Host#g" /etc/sysconfig/network-scripts/ifcfg-eth[01]  &>/dev/nullif [ $? -eq 0 ];thenecho "主机的IP地址修改成功!"read -p "是否确认重启网络服务进行生效![yes|no]:" Conif [ "$Con" == "yes" ];thenecho "你选择了重启网络服务生效!注意:重启之后,当前连接会断开,需要使用新的IP地址进行连接。"systemctl restart  network &>/dev/nullif [ $? -ne 0 ];then echo "重启网络服务失败!"fielseecho "你没有选择重启网络服务!你可以选择手动重启!"fielseecho "主机的IP地址修改失败!"fi
elseecho "你选择不修改IP地址,再见!"
fi
[root@shell /scripts]# sh read-6.sh
请输入你要修改之后的IP地址的主机位:180
是否确认修改主机的IP地址[yes|no]:no
你选择不修改IP地址,再见!
[root@shell /scripts]# sh read-6.sh
请输入你要修改之后的IP地址的主机位:180
是否确认修改主机的IP地址[yes|no]:yes
你选择了修改主机的IP地址.....
主机的IP地址修改成功!
是否确认重启网络服务进行生效![yes|no]:no
你没有选择重启网络服务!你可以选择手动重启!
[root@shell /scripts]# sh read-6.sh
请输入你要修改之后的IP地址的主机位:170
是否确认修改主机的IP地址[yes|no]:yes
你选择了修改主机的IP地址.....
主机的IP地址修改成功!
是否确认重启网络服务进行生效![yes|no]:yes
你选择了重启网络服务生效!注意:重启之后,当前连接会断开,需要使用新的IP地址进行连接。3、查看当前内存的使用率,大于80%,则进行报警
#思路:
1. 怎么查看内存的使用情况 free -m
2. 怎么获取已使用的内存使用率 awk '/^Mem/{print $3/$2*100}
3. 怎么进行对比,使用率大于80%,获取整数
4. 根据判断,返回结果,大于80%则报警,正常就正常提示#脚本:
vim free_use.sh
#!/bin/bash
Free_Used=$(free -m | awk '/^Mem/{print $3/$2*100}')
if [ ${Free_Used%.*} -ge 80 ];thenecho -e "\033[31m当前内存使用率过高!使用率为:${Free_Used.*}%\033[0m"
elseecho -e  "\033[32m当前内存使用率正常!使用率为:${Free_Used%.*}%\033[0m"
fi
[root@shell /scripts]# sh free_use.sh
当前内存使用率过高!使用率为:87%
[root@shell /scripts]# sh free_use.sh
当前内存使用率正常!使用率为:9%4、打包后还原文件名
#要求
1、在/oldboy目录下,存在很多文件,找出所有以.txt为结尾的文件
2、批量的修改所有以.txt为结尾的文件重命名为.txt.bak
3、把所有的以.bak的文件打包压缩
4、批量还原.bak的文件重名为.txt#第一种方法
[root@shell /scripts]# cat mv.sh
#!/bin/bash
find /oldboy/ -type f -name "*.txt" | awk '{print "mv",$0,$0".bak"}' | bash &>/dev/null
if [ $? -eq 0 ];thenecho "所有.txt结尾的文件全部重命名为.txt.bak成功......"
elseecho "重命名失败!"exit
ficd /oldboy && tar czf bak.tar.gz $(find /oldboy -type f -name "*.bak") &>/dev/null
if [ $? -eq 0 ];thenecho "所有以.bak为结尾的文件打包压缩成功........"
elseecho "打包压缩失败!"exit
fifind /oldboy -type f -name "*.bak" | awk -F '.' '{print "mv",$0,$1"."$2}' | bash &>/dev/null
if [ $? -eq 0 ];thenecho "所有.bak为结尾的文件还原名称为.txt成功........"
elseecho "还原名称失败!"exit
fi

7、变量运算

1、# let 计数,只能针对变量,不能对数字进行操作
a=10
let a++
let a++
echo $a
12a=10
let a=a+9
echo $a
192、#运算
num1  +  num2  加
num1  -  num2   减
num1  *  num2   乘
num1  /  num2   除
num1  %  num2   求余
num1  ^  num2   求次方2.1、# expr 运算变量与预算符号之间必须空格,不能进行求次方运算
expr $num1 + $num2
expr $num1 - $num2
expr $num1 \* $num2
expr $num1 / $num2
expr $num1 % $num22.1.1、计算字串长度,空格也算expr length "this is a test"142.1.2、抓取字串,从第3位开始抓5个位置的字符,空格也算expr substr "this is a test" 3 5is is2.1.3、抓取第一个字符在字符串中出现的位置数,空格也可以抓expr index "sarasara" a2expr index "this is a test" ' '52.2、# $(()) 没有严格格式要求,不能进行求次方运算
echo $(($num1+$num2))
echo $(( $num1 + $num2 ))
echo $(( $num1 - $num2 ))
echo $(( $num1 * $num2 ))
echo $(( $num1 / $num2 ))
echo $(( $num1 % $num2 ))
# $[] 没有严格格式要求,不能进行求方运算
echo $[$num1+$num2]
echo $[1+1]
echo $[ $num1 - $num2 ]
echo $[ $num1 * $num2 ]
echo $[ $num1 / $num2 ]
echo $[ $num1 % $num2 ]
# python运算命令,没有严格格式要求,不能进行求方运算, .0 表示计算到小数位11位
a=10
b=3
echo "print ${a}.0/$b" | python
3.33333333333echo print 11/3 >123.txt
python 123.txt
3# bc 运算命令,能进行求方运算,scale 用来设置小数位数
echo 10 + 20 | bc
echo $num1 + $num2 | bc
echo 1 \* 2 |bc
echo $num1 / $num2 | bc
echo "scale=2;$num1 / $num2" | bc
echo "$num1 ^ $num2" | bc
# awk 运算命令,能进行求方运算,%.3f 设置小数位数, \n 表示回车,-v 设置命令内部变量
awk 'BEGIN{print 10 + 5}'
awk 'BEGIN{print 10 - 5}'
awk 'BEGIN{print 10 * 5}'
awk 'BEGIN{print 10 / 5}'
awk 'BEGIN{print 10 % 5}'
awk 'BEGIN{print 10 ^ 5}'
awk 'BEGIN{printf "%.3f\n",10/3}'
awk -vnum1=10 -vnum2=5  'BEGIN{print num1/num2}'
#awk如果想使用外部变量必须用双引号 "......"
awk "BEGIN{print $a+$b}"#实战 计算内存使用率
ps aux | awk 'NR>1{print $5}' | xargs | tr ' ' '+' | bcps aux | awk 'NR>1{i+=$5}END{print i}'[root@shell /scripts]# cat for_vsz.sh
#!/bin/bash
a=0
b=0
c=0
d=0
e=0
for i in $(ps aux|awk 'NR>1{print $5}')
doa=$(echo $[$a+$i])b=$(expr $b + $i)c=$(echo "$c+$i"|bc)d=$(echo "print ${d}+$i"|python)e=$(awk "BEGIN{print $e+$i}")
done
echo a=$a
echo b=$b
echo c=$c
echo d=$d
echo e=$e

Shell内置命令【循环控制】

# 等待上一条命令执行完
wait
# 结束循环
1、忽略本次循环剩余的代码,直接执行下一次循环
continue
2、跳出循环,并不结束脚本,继续执行循环外面的命令
break
3、退出脚本
exit

shell脚本流程控制

1、判断语句 if

1.1语法
#单分支
if [ 满足条件 ];then执行这里的命令
fi#双分支
if [ 满足条件 ];then执行这里的命令
else执行这里的命令
fi#多分支
if [ 满足条件1 ];then执行这里的命令
elif [ 满足条件2 ];then执行这里的命令
elif [ 满足条件3 ];then执行这里的命令
else执行这里的命令
fi
1.2文件比较
-e 文件或者目录存在为真                [ -e file/dir ]
-s 文件存在且不为空为真【判断文件是否是空文件】,只针对文件-r 文件存在且可读为真
-w 文件存在且可写为真
-x 文件存在且可执行为真-f 文件存在且是一个常规文件为真
-d 文件存在且是一个目录为真-c 文件存在且是一个特殊字符为真
-b 文件存在且是一个特殊块文件为真
-p 文件存在且是一个命名管道为真
-S 文件存在且是一个套接字为真-u 文件存在且设置了suid位
-g 文件存在且设置了sgid位-nt 第一个文件比第二个文件新为真
-ot 第一个文件比第二个文件旧为真
-ef 第一个文件有硬连接到第二个文件为真
-L 符号链接文件
1.3整数比较
-eq          等于条件则为真           [ 1 -eq 1 ]-ne            不等于                  [ 1 -ne 2 ]-gt         大于                    [ 2 -gt 1 ]-ge            大于等于                 [ 2 -ge 2 ]-lt         小于                    [ 1 -lt 2 ]-le        小于等于                 [ 1 -le 1 ]hostnamectl set-hostname mcy &>/dev/null
if [ $? -eq 0 ] ; thenecho "上一条命令修改主机名成功"
elseecho "上一条命令修改主机名失败"
fifor i in When find examines or prints information a file
do[ ${#i} -lt 5 ] && echo $i
doneread -p "袁帅>樟瑜" 是否成功 【y/n】:KO
if [ "$KO" == "y" ];thenecho "打的好"
else echo "下次再打"
fi
1.4字符比较
-z   为空为真
[root@shell01 ~]# a=123
[root@shell01 ~]# [[ -z $a ]] && echo "真" || echo "假"
假
-n  不为空为真
[root@shell01 ~]# b=
[root@shell01 ~]# [[ -n $b ]] && echo "真" || echo "假"
假#!/bin/bash
a=1
b=
if [[ -z $a ]]; thenecho a 真
elseecho a 假
fi
if [[ -z $b ]]; thenecho b 真
elseecho b 假
fi==  相同为真
[root@shell01 ~]# [[ a == a ]] && echo "真" || echo "假"
真
[root@shell01 ~]# [[ a == b ]] && echo "真" || echo "假"
假
[root@shell01 ~]# [[ 1 == 1 ]] && echo "真" || echo "假"
真
[root@shell01 ~]# [[ 1 == 2 ]] && echo "真" || echo "假"
假
!= 不相同为真
[root@shell01 ~]# [[ 1 != 2 ]] && echo "真" || echo "假"
真<   字符在字典中顺序排在前为真
[root@shell01 ~]# [[ a < b ]] && echo "真" || echo "假"
真
[root@shell01 ~]# [[ c < b ]] && echo "真" || echo "假"
假
>    字典顺序排在后为真
[root@shell01 ~]# [[ c > b ]] && echo "真" || echo "假"
真
[root@shell01 ~]# [[ a > b ]] && echo "真" || echo "假"
假
1.5多条件比较
#使用下面两个符号作为条件比对,必须使用单中括号
-a   并且    当多个条件存在时,必须是条件成立才为真,如果有一个条件不为真时,则条件为假
-o   或者    当多个条件存在时,必须是所有条件不为真时则为假,如果有一个条件为真时,则整体条件为真
#!/bin/bash
if [ 1 -eq 1 -a 2 -gt 1 ];thenecho "对"
elseecho "错"
fi#使用下面两个符号作为条件比对,必须使用双中括号
&&   并且
||    或者
[[ 3 -lt 2 ||  2 -gt 3 ]] && echo "为真" || echo "为假"
[[ 3 -lt 2 &&  2 -gt 3 ]] && echo "为真" || echo "为假"
1.6正则比较
#在进行正则比较的时候,必须使用双中括号
[[ "$USER" =~ ^r ]] && echo "为真" || echo "为假"
为真#正则比较时,变量以外的任何字符不可以用双引号 "" 引起来
[[ "$USER" =~ "^r" ]] && echo "为真" || echo "为假"
为假
[[ "$USER" =~ '^r' ]] && echo "为真" || echo "为假"
为假#!/bin/bash
if [[ "$USER" =~ ^r ]]; thenecho 匹配于
elseecho 不匹配
fi

2、流程控制 case

#语法:case 变量 in变量值1)命令序列;;变量值2)命令序列;;变量值N)命令序列;;*)命令序列exit
esac#!/bin/bash
cat<<EOF
############################
1、糖醋排骨     价格: 35 元
2、鱼香肉丝     价格: 15 元
3、水煮鱼       价格: 45 元
0、结束点菜
############################
EOF
read -p "你想点什么菜:" a
case $a in1)echo "你点了 糖醋排骨";;2)echo "你点了 鱼香肉丝";;3)echo "你点了 水煮鱼";;*)echo "你点的菜没有"exit
esac

3、循环语句 for

#当条件为真,则执行循环体,如果条件为假,则结束循环#取值列表,很多种取值方法,默认以空白字符为分割符
1、for i in file1 file2 file3#当取值列表中值出现空格的情况下,需要使用引号进行括起来
2、for i in 'file1 test' file2 file3#取值列表中出现特殊字符,则使用转义字符进行转义
3、for i in file1 \( file2 file3#根据变量进行取值
4、List="file1 file2 file3"for i in  $List#通过命令中取值
5、for i in  $(cat /etc/hosts)#自定义分隔符,以冒号为分隔符  或者  #指定多个分隔符 或者  #以换行符作为分隔符
6、IFS=:                     或  IFS=':;/'        或   IFS=$'\n'for i in  $(cat /etc/passwd | head -1)
-------------------
for 变量 in 取值列表
do循环体
done
-------------------#C语言风格的for
-----------------------------------------------------------
#!/bin/bash
for i in {1..10}
doecho $i
done#给变量 i 赋值,从0开始,每次加1,然后依次循环打印出变量 i 的值
for (( i = 0; i < 10; i++ )); doecho $i
done#!/bin/bash
for ((i=0;i<10;i++))
doecho $i
done#定义多个变量,输出1-9的升序和降序
#!/bin/bash
for ((a=1,b=9;a<10;a++,b--))
doecho $a $b
done
-----------------------------------------------------------#正常写法
#!/bin/bash
a=0
b=10
for i in {1..9}
dolet a++let b--echo $a $b
done#将多个字符串用空格分开,依次将字符串赋值给变量 i ,然后循环查找字符数小于5的字符串,并且打印出来
for i in When find examines or prints information a file
do[ ${#i} -lt 5 ] && echo $i
done

4、循环语句 while

只要条件成立,就会反复执行循环语句,直到条件不成立时,才会退出。语法:#第一种,适合满足条件就不停的循环,直到条件不被满足为止才结束循环
while 满足条件
do循环体
done
#例子:
[root@shell01 ~]# vim while1.sh
#!/bin/bash
i=0
while [ $i -lt 3 ]
dolet i++echo $i
done
#执行结果:
[root@shell01 ~]# sh while1.sh
1
2
3#第二种,适合菜单,每次选择都会显示菜单,直到选择事先设定的结束循环语句
while true
do循环体
done#第三种,从 path.txt 文件中依次读取每一行,read line 就代表读取每一行的意思
while read line
do 循环体
done < path.txt

函数

1、函数调用

#引用函数库
[ -f /etc/init.d/functions ] && source /etc/init.d/functions || echo "函数库不存在!"
#调用函数库
systemctl start rsyncd
if [ $? -eq 0 ];thenaction "服务Rsync启动成功................" /bin/trueelseaction "服务Rsync启动失败................" /bin/false
fi#定义函数
#第一种
函数名() {命令集合
}
-------------------
menu(){echo nihao
pwd
}
-------------------#第二种
function 函数名 {命令集合
}
-------------------
function 函数名 {echo nihao
pwd
}
-------------------#设置函数,这里试用的是菜单内容
menu() {cat<<EOF
#########主菜单############
1. 安装Nginx服务
2. 安装PHP服务
3. 退出脚本
##########################
EOF
}
#调用菜单
menu#命令行下试用函数
[root@shell01 ~]# fun1() { echo "okko"; }
[root@shell01 ~]# fun1
okko
[root@shell01 ~]# function fun2 { echo "321"; }
[root@shell01 ~]# fun2
321
[root@shell01 ~]# fun3() { echo "$2"; }
[root@shell01 ~]# fun3 a b c d e
b
[root@shell01 ~]# fun4() { echo "$*"; }
[root@shell01 ~]# fun4 a b c d e
a b c d e
[root@shell01 ~]# fun5() { echo "$@"; }
[root@shell01 ~]# fun5 a b c d e
a b c d e

2、函数中定义变量区别

#local 设置只在函数中使用的变量[root@shell01 ~]$ cat test.sh
#!/bin/bash
#设置函数 testvar
testvar()
{local num=10((num++))echo "函数变量:$num"a=100
}
#调用函数 testvar
testvar
echo "函数外打印 local 设置的函数中变量:$num"
echo "函数外打印普通设置的函数中变量:$a"
[root@shell01 ~]$ sh test.sh
函数变量:11
函数外打印 local 设置的函数中变量:
函数外打印普通设置的函数中变量:100

3、函数状态返回

#返回值在shell中有两种方式echo     #返回数据,自定义的输出 数据 字符串return        #命令的执行结果返回值  0-255 之间(包含本身)的正整数  #用 $? 来判断# 0 默认表示成功,非 0 表示失败[root@shell ~]# vim return.sh
check_num() {read -p "请输入一个数字:" Numif [ $Num -ge 0 -a $Num -lt 10 ];thenreturn 0elif [ $Num -ge 10 -a $Num -lt 20 ];thenreturn 1elif [ $Num -ge 20 -a $Num -lt 30 ];thenreturn 2elsereturn 3fi
}
check_num
Rc=$?
if [ $Rc -eq 0 ];thenecho "你输入的数字大于等于0且小于10."
elif [ $Rc -eq 1 ];thenecho "你输入的数字大于等于10且小于20."
elif [ $Rc -eq 2 ];thenecho "你输入的数字大于等于20且小于30."
elseecho "你输入的数值超出范围!请重新输入!"echo $Rc
fi[root@shell ~]# sh return.sh
请输入一个数字:0
你输入的数字大于等于0且小于10.
[root@shell ~]# sh return.sh
请输入一个数字:10
你输入的数字大于等于10且小于20.
[root@shell ~]# sh return.sh
请输入一个数字:20
你输入的数字大于等于20且小于30.
[root@shell ~]# sh return.sh
请输入一个数字:30
你输入的数值超出范围!请重新输入!
3

数组

1、数组的概述

什么是数组简单来讲:数组其实就是变量的一种,变量只能存储一个值,而数组可以存储多个值数组的分类分为两类  普通数组  关联数组普通数组:只能使用正整数作为数组索引关联数组:可以使用字符串作为数组索引索引:数组中每个值对应一个索引号,默认从0开始,也可以自由设置元数:就是数组内 值 的数量,也可以称为索引的数量#显示已定义的普通数组
declare -a
#显示所有已定义的关联数组
declare -A

2、数组的基本使用

#定义数组
1、普通数组#声明普通数组 declare -a 数组名 定义普通数组 无需声明
#定义方法一:分开定义
shuzu_1[0]=nginx
shuzu_1[1]=php-fpm
shuzu_1[2]=mysql
shuzu_1                 #数组名
0 1 2                   #索引号
nginx php-fpm mysql     #值#定义方法二:一次性定义多个值
shuzu_2=(oldboy oldgirl oldqiu)#定义方法三:通过命令的执行结果进行定义  默认以空白字符为分隔符
shuzu_3=($(cat /etc/hosts))#定义方法四:自定义索引序列号
shuzu_4=(beijing shanghai [5]=wuhan [10]=nanjing)#打印数组中所有的值
echo ${shuzu_1[@]}
nginx php-fpm mysql
echo ${shuzu_1[*]}
nginx php-fpm mysql
echo ${shuzu_1[0]}
nginx
echo ${shuzu_1[1]}
php-fpm#打印数组中的从索0开始打印,显示所有
echo ${shuzu_1[@]:0}
nginx php-fpm mysql
#打印数组中的从索0开始打印,显示2个
echo ${shuzu_1[@]:1:2}
php-fpm mysql#打印数组的所有的索引号
echo ${!shuzu_4[@]}
0 1 5 10
echo ${!shuzu_3[@]}
0 1 2 3 4 5 6 7 8 9#打印数组的元数个数【索引的个数】
echo ${#shuzu_1[@]}
3
echo ${#shuzu_3[@]}
102、关联数组#声明关联数组 declare -A 数组名 定义关联数组 需要声明【一定要先声明后定义关联数组】
#定义方法一:分开定义
declare  -A  shuzu_1
shuzu_1[name]=qiudao
shuzu_1[age]=18
shuzu_1[skill]=linux#定义方法二:一次性定义多个值
declare  -A  shuzu_2
shuzu_2=([index1]=nginx [index2]=mysql [index3]=php)#取消定义数组的值
[root@shell01 ~]$ a=(oldboy oldgirl oldqiu)
[root@shell01 ~]$ echo ${a[*]}
oldboy oldgirl oldqiu
[root@shell01 ~]$ unset a[2]
[root@shell01 ~]$ echo ${a[*]}
oldboy oldgirl
[root@shell01 ~]$ unset a[@]
[root@shell01 ~]$ echo ${a[*]}[root@shell01 ~]$

3、数组的遍历与循环

1、普通数组赋值与遍历
[root@shell01 ~]$ cat shuzu.sh
#!/bin/bash
while read line
dohosts[i++]=$line
done </etc/hosts
for i in ${!hosts[@]}
doecho "hosts数组的索引为$i ,对应值为:${hosts[i]}"
done
[root@shell01 ~]$ sh -x shuzu.sh
+ read line
+ hosts[i++]='127.0.0.1   ...... localhost4 localhost4.localdomain4'
+ read line
+ hosts[i++]='::1         ...... localhost6 localhost6.localdomain6'
+ read line
+ for i in '${!hosts[@]}'
+ echo 'hosts数组的索引为0 ,对应值为:127.0.0.1   ...... localhost4 localhost4.localdomain4'
hosts数组的索引为0 ,对应值为:127.0.0.1   ...... localhost4 localhost4.localdomain4
+ for i in '${!hosts[@]}'
+ echo 'hosts数组的索引为1 ,对应值为:::1         ...... localhost6 localhost6.localdomain6'
hosts数组的索引为1 ,对应值为:::1         ...... localhost6 localhost6.localdomain62、关联数组赋值与遍历
[root@shell01 ~]$ cat test.sh
#!/bin/bash
#1.声明关联数组
declare -A Shell_count
#2.对数组进行赋值
while read line
doType=$(echo $line|awk -F: '{print $NF}')let Shell_count[$Type]++
done < /etc/passwd
#3.遍历
for i in ${!Shell_count[@]}
doecho -e "Shell:$i \t Count:${Shell_count[$i]}"
done
[root@shell01 ~]$ sh test.sh
Shell:/sbin/nologin  Count:17
Shell:/bin/sync      Count:1
Shell:/bin/bash      Count:5
Shell:/sbin/shutdown     Count:1
Shell:/sbin/halt         Count:1↑                 ↑
#注意: 索引                  值#如果上面的脚本不理解就先看下面
[root@web01 ~]# declare -A b
[root@web01 ~]# b[/bin/bash]=1
[root@web01 ~]# echo ${b[/bin/bash]}
1
[root@web01 ~]# let b[/bin/bash]++
[root@web01 ~]# echo ${b[*]}
2/bin/bash  是索引
let b[/bin/bash]++    表示将 b[/bin/bash] 对应的值 +1

通配符、特殊符号、特定的字符

#通配符及特殊符号
*       #所有
.       #当前目录
..      #当前目录的上一级目录
-       #当前目录的上一次所在的目录
~       #家目录
#       #注释,超级管理员的命令行提示符
$       #引用变量,普通用户的命令行提示符
?       #匹配任意一个字符,必须是一个
!       #非,取反
[]      #匹配中括号中任意一个字符
{}      #生成序列,整体
[^]     #排除中括号中所有字符
``        #优先执行反引号里面的命令
$()     #优先执行里面的命令
&&      #前面一个命令执行成功,才会执行后面的命令
||      #前面的命令执行失败,才会执行后面的命令
|       #管道,将前面的命令的输出结果交给管道后面的命令
\       #转义字符,取消一些特殊字符的含义
&       #将程序放到后台运行#特定的字符
[[:upper:]]   所有大写字母    =  grep '[A-Z]' passwd
[[:lower:]]   所有小写字母    =   grep '[a-z]' passwd
[[:alpha:]]   所有字母        =        grep '[a-Z]' passwd
[[:space:]]   所有空白字符    =  grep '^[ \t]*$' passwd
[[:digit:]]   所有数字        =        grep '[0-9]' passwd
[[:alnum:]]   所有字母数字    =  grep '[0-9,a-Z]' passwd
[[:punct:]]   所有特殊符号    =  #特殊字符换码序列:\r  -  回车\n  -  换行\b  -  退格\t  -  制表符【TAB键】\s  -  空格、回车、TAB键、垂直制表符\v  -  垂直制表符\"  -  双引号\'  -  单引号

正则符号

#正则表达式
注意事项:正则神坑    中文字符
正则符号(RE)    基本正则表达式(BRE)    扩展正则表达式(ERE)#基本正则
^       #开头
$       #结尾
^$      #空行
\       #转义字符
.       #任意一个字符,除了换行符
[]      #匹配中括号中的任意一个字符
[^]     #匹配[^]之外的所有字符
[a-z]   #匹配所有小写字母
[0-9]
.*      #所有
*       #匹配前面的字符出现0次或者0次以上#扩展正则
?       #匹配前面的字符出现0次或者1次
+      #匹配前面的字符出现1次或者1次以上
()      #整体,后向引用,创建一个用于匹配的字符串
{n}     #n数字, 前面的字符出现n次
{n,}    #前面的字符至少出现n次
{n,m}   #前面的字符出现至少n次,最多m次,m一定要大于n
{,m}    #前面的字符最多出现m次
|       #或者

grep

grep     #三剑客老三  过滤  过滤出来的内容是有颜色
[root@shell ~]# alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'选项:-c              只统计包含关键字的行数有多少行-n               显示关键字所在的行数和内容-o             只显示关键字-i                忽略大小写 -v                排除-w                精确匹配-A num(数字)     显示过滤出来的内容向下几行-B num(数字)   显示过滤出来的内容向上几行-C num(数字)   显示过滤出来的内容向上向下各几行-E             支持扩展正则-l                列出包含关键字的文件列表-r              在当前目录及其子目录下搜索包含'关键字'行的文件,也可指定搜索目录

sed

三剑客的老二   擅长替换 流编辑器  非交互式的编辑器。  Sed的工作原理
sed 可以同时处理多个文件,增删改查
sed 处理文件时,按照行进行处理内容,首先会将第一行取出放在一个缓冲区中,这个缓冲区我们称之为模式空间。处理文件时,如果行内容匹配成功,就会将匹配内容输出到屏幕,如果行内容不匹配,则将之丢弃。接着处理下一行,同样的操作,直到文件结束。文件的内容其实并没有改变,如果想真正的改变,需要加上-i选项。sed 正则使用,跟grep相差不大,使用扩展正则时, 需要使用-r选项
sed 的语法:
sed [选项] command files
选项:-n        #取消默认输出-i       #修改文件内容-r       #支持扩展正则-e       #多项编辑sed 的内部命令a     #追加i        #插入p        #打印和 -n 配合使用d       #删除s        #替换g        #全局c        #在当前行位置进行替换!        #取反=       #显示行号w      #写文件命令i     #忽略大小写
了解n     #读入下一行,从下一条命令进行处理h       #把模式空间里的内容重定向到暂存缓冲区 H       #把模式空间里的内容追加到暂存缓冲区  g       #取出暂存缓冲区的内容,将其复制到模式空间,覆盖原处的内容G        #取出暂存缓冲区的内容,将其复制到模式空间,追加到原处的内容的后面[root@shell /scripts/shell13]# sed -n '/root/p' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@shell /scripts/shell13]# sed -n '/root/wnewfile.txt' passwd
[root@shell /scripts/shell13]# ll newfile.txt
-rw-r--r-- 1 root root 77 2020-03-06 15:15 newfile.txt
[root@shell /scripts/shell13]# cat newfile.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@shell /scripts/shell13]# sed -n '2w newfile-2.txt' passwd
[root@shell /scripts/shell13]# cat newfile-2.txt
bin:x:1:1:bin:/bin:/sbin/nologin

awk

1、awk理论

awk是一个编程语言主要作用:对文本和数据的处理awk处理数据的流程1. 扫描文件内容,从上到下进行扫描,按照行进行处理的。2. 寻找匹配到的内容,进行读取到特定的模式中,进行行处理3. 行满足指定模式动作,则输出到屏幕上面,不满足丢弃4. 接着读取下一行继续处理,接着循环,直到文件的结尾awk语法格式awk [选项]  command   files三种格式行处理前        行处理中          行处理后BEGIN          执行的命令       最后的显示  ENDawk的工作原理1. awk将文件中每一行作为输入,将每一行的数据赋值给内部变量 $0 2. awk有开始进行字段分解,根据指定的分隔符,将每个字段进行赋值给内部变量 $1 $2 $3 3. awk默认的分割为空白字符,由内部变量FS来确定,也可以使用-F进行指定对应的分隔符4. awk处理时使用print进行打印你分割后的字段5. awk打印输出结果之后,不同字段之间由空格进行分割,这个空格是由不同字段之间的逗号进行映射的,由内部变量OFS进行修改, OFS默认的输出分割符就是空格6. awk输出一行内容之后,从新读取下一行内容,会覆盖内部变量$0,然后新的字符进行字段分割并进行处理。#awk的命令格式
匹配模式  动作

2、awk内部变量

1、FS    输入分隔符  默认以空白字符为分隔符
awk -F: '{print $1}' passwd
awk 'BEGIN{FS=":"}{print $1}' passwd2、OFS   默认输出分割为空格,  打印的时候用逗号作为分割,逗号就是输出分割符,在显示的时候,默认映射为空格
awk -F: -vOFS="@" '{print $1,$2}' passwd
root@x 0
awk -F:  'BEGIN{OFS="$"}{print $1,$2}' passwd
root$x 03、NF  表示每一行最后一列是第几列   $NF  打印最后一列的内容  $(NF-1) 打印倒数第2列
awk -F: '{print NF}' passwd
6
awk -F: '{print $NF}' passwd
/bin/bash
awk -F: '{print $(NF-1)}' passwd4、$0  表示整行内容5、NR  表示是行号
awk '{print NR,$0}' passwd
1 root:x 0:100:root:/root:/bin/bash
2 bin:x 1:200:bin:/bin:/sbin/nologin
awk 'NR==1' passwd
root:x 0:100:root:/root:/bin/bash5、FNR  显示行号,针对多个文件同时进行处理,不同的文件显示各自的行号
awk '{print FNR,$0}'  passwd  test.txt
1 root:x 0:100:root:/root:/bin/bash
2 bin:x 1:200:bin:/bin:/sbin/nologin
......
1 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
2     link/ether 00:0c:29:c5:ab:bf brd ff:ff:ff:ff:ff:ff
3  /   inet 10.0.0.170/24 brd 10.0.0.255 scope global eth0
......7、RS 输入记录分隔符   ORS   输出记录分隔符8、awk格式化输出
awk -F:  '{print "用户为:"$1,"UID为:"$3,"GID为:"$4}'    /etc/passwd
用户为:root UID为:0 GID为:0
用户为:bin UID为:1 GID为:1
awk -F:  '{printf "%-20s %-10s %-10s\n",  "用户为:"$1,"UID为:"$3,"GID为:"$4}'    /etc/passwd
用户为:root             UID为:0     GID为:0
用户为:bin              UID为:1     GID为:1

3、awk模式动作

1、正则表达式
awk '/^root/' /etc/passwd
awk '$0 ~/^root/' /etc/passwd
awk -F: '$4 ~/^root/' passwd
awk '!/^root/' passwd
awk '$0 !~/^root/' passwd
awk -F: '$4 !~/^root/' passwd2、比较表达式
#关系运算符
<        小于
<=      小于等于
==        等于
>        大于
>=      大于等于
!=     不等于
awk -F: '$3 == 0'  passwd
awk -F: '$3==0'  passwd
awk -F: '$3==0{print $0}' passwd
awk -F: '$3<5' passwd
awk -F: '$3<5{print $0}' passwd
awk -F: '$3>5{print $0}' passwd
awk -F: '$3>=5{print $0}' passwd
awk -F: '$3<=5{print $0}' passwd
awk -F: '$1 == "root"' passwd
awk -F: '$4 == "root"' passwd
awk -F: '$4 != "root"' passwd
df | awk '/\/$/'
df | awk '/\/$/' | awk '$3 > 2100000{print $4}'
df | awk '/\/$/{if($3>2000000)print $4}'3、条件表达式
awk -F: '{if($3>20000)print $0}' /etc/passwd
awk -F: '{if($3>1000){print $NF} else {print $1}}' /etc/passwd4、运算表达式
awk -F: '$3 * 100 > 50000 ' /etc/passwd
awk -F: '{if($3*10>1000){print $NF} else {print $3}}' /etc/passwd
awk -F: '/sync/{print $3}' passwd
awk -F: '/sync/{print $3 + 10}' passwd
awk -F: '/sync/{print $3 -2}' passwd
awk -F: '/sync/{print $3*2}' passwd
awk -F: '/sync/{print $3/5}' passwd
awk -F: '/sync/{print $3^5}' passwd
awk -F: '/sync/{print $3%5}' passwd
awk -F: '/sync/{print $3+$4}' passwd
awk -F: '/sync/{print $3-$4}' passwd
awk -F: '/sync/{print $3*$4}' passwd
awk -F: '/sync/{print $3/$4}' passwd5、逻辑操作符
&&  并且
||  或者
!  非
awk 'NR>2 && NR<4' passwd
awk 'NR>2 || NR<4' passwd
awk 'NR!=1' passwd
awk -F: '$1 ~/root/ && $3 > 10' passwd
awk -F: '$1 ~/root/ || $3 > 10' passwd
awk '!/^root/' passwd打印文件datefile中包含west的行
# awk '/west/' datafile
打印文件datefile中以north开头的行
# awk '/^north/' datafile
打印文件datefile中第三列以north开头的行
# awk '$3 ~ /^north/' datafile
打印文件datefile中以no或者so开头的行
# awk '/^(no|so)/' datafile
打印文件datefile中 第3列空格第2列
# awk '{print $3,$2}' datafile
打印文件datefile中 第3列第2列
# awk '{print $3 $2}' datafile
打印文件datefile中所有列
# awk '{print $0}' datafile
打印文件datefile中 Number of fields:最后一列
# awk '{print "Number of fields: "NF}' datafile
打印文件datefile中 包含northeast行的第3列空格第2列
# awk '/northeast/{print $3,$2}' datafile
打印文件datefile中 以n或s开头的行的第1列
# awk '/^[ns]/{print $1}' datafile
打印文件datefile中 第5列匹配于. 789最少1个最多N个的行,因为默认是空格分隔符,所以结果为空
# awk '$5 ~ /\. [7-9]+/' datafile
打印文件datefile中 第2列中不包含E的行,第1列空格第2列
# awk '$2 !~ /E/{print $1,$2}' datafile
打印文件datefile中 第3列中以Joel开头的行的第3列is a nice boy.
# awk '$3 ~ /^Joel/{print $3 "is a nice boy."}' datafile
打印文件datefile中 第8列中以2位数结尾的行的第8列
# awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile
条件 第4列中以Chin结尾的行
动作 打印 The price is $第8列.
# awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' datafile
条件 包含Tj的行
动作 打印 所有列.
# awk '/Tj/{print $0}' datafile
条件 以:分隔符
动作 打印 Number of fields: 最后一列
# awk -F: '{print "Number of fields: "NF}' /etc/passwd
条件 以空格或:分隔符
动作 打印 最后一列
# awk -F"[ :]" '{print NF}' /etc/passwd

4、Awk判断语句

if
awk -F: '{if($3==0){i++}}END{print "当前系统管理员用户的数量为:"i}' /etc/passwd
if  else
awk -F: '{if($3==0){i++}else{j++}}END{print "管理员的数量为:"i;print "其它用户数量为:"j}' passwd
if  else  if  else
awk -F: '{if($3==0){a++}else{if($3>0 && $3<1000){b++}else{c++}}}END{print "管理员数量为:"a,"系统用户数量为:"b,"普通 用户数量为:"c}' /etc/passwd

5、Awk循环语句

for
awk 'BEGIN{for(a=1;a<=10;a++){print a}}'
awk 'BEGIN{for(a=1;a<=10;a++){print "useradd  qiudao"a}}' |bash
awk 'BEGIN{for(a=1;a<11;a++){print "date -s 2020/03/"a"&>/dev/null  &&  touch `date +%F`.txt"}}' |bashwhile
awk 'BEGIN{a=1;while(a<11){print a;a++}}'
awk 'BEGIN{a=1;while(a<11){print "useradd  shanghai"a;a++}}' |bash
awk 'BEGIN{a=1;while(a<11){print "date -s 2020/03/"a" &>/dev/null && touch `date +%F`.log ";a++}}' |bash

6、Awk数组

计算   求和   +=
统计   次数   ++
1. 计算数字1-100之间的和
seq 100 |awk '{he+=$1}END{print he}'
2. 计算出访问日志所有IP的响应返回的总字节数
awk '{zong+=$10}END{print zong}' access.log
3. 统计出/etc/passwd文件中每个shell的数量
awk -F: '{count[$NF]++}END{for (i in count)print i,count[i]}' /etc/passwd
4. 取出访问日志中每个IP的访问次数
awk '{ips[$1]++}END{for (i in ips)print i,ips[i]}' access.log |sort -rnk2 |head
5. 统计出tcp的11种状态的数量
netstat -ant |awk 'NR>2{state[$NF]++}END{for (i in state)print i,state[i]}'
6. 统计出secure.log日志中破解你密码次数最多的10个IP
awk '/Failed/{ip[$(NF-3)]++}END{for (i in ip)print i,ip[i]}' secure.log|sort -rnk2|head|column -t
7. 统计出访问日志中每个IP的访问次数和每个IP对应返回的字节数量
[root@shell ~]# awk '{ips[$1]++;he[$1]+=$10}END{for (i in ips)print i,ips[i],he[i]}' access.log  |sort -rnk2 | head |column  -t
8. 统计出访问日志中每个IP的每种状态码的数量
awk '{status[$1" "$9]++}END{for (i in status)print i,status[i]}' access.log| sort -rnk3 | grep 139.226.172.217

timeout

用来控制程序运行的时间。运行指定的命令,如果在指定时间后仍在运行,则杀死该进程
Usage: timeout [OPTION] NUMBER[SUFFIX] COMMAND [ARG]...
SUFFIX 默认值是”s”代表秒,”m”代表分,”h”代表小时,”d”代表天长选项必须使用的参数对于短选项时也是必需使用的。-s, --signal=信号指定在超时时发送的信号。信号可以是类似"HUP"的信号名或是信号数。查看"kill -l"以获得信号列表--help        显示此帮助信息并退出--version        显示版本信息并退出如果程序超时则退出状态数为124,否则返回程序退出状态。
如果没有指定信号则默认为TERM 信号。TERM 信号在进程没有捕获此信号时杀死进程。
对于另一些进程可能需要使用KILL (9)信号,当然此信号不能被捕获。如果timeout后的命令在规定时间内完成,返回0;否则返回非0
#范例
timeout 2 echo 1
echo $?
0timeout 2 sleep 100
echo  $?
124

expect

expect 脚本语言中交互处理常用命令

1. #!/usr/bin/expect告诉操作系统脚本里的代码使用那一个 shell 来执行。这里的 expect 其实和 Linux 下的 bash、windows 下的 cmd 是一类东西。注意:这一行需要在脚本的第一行,从而告知操作系统采用 expect 作为 shell 执行脚本。
注意:当使用 #!/usr/bin/expect -d 时,expect 脚本将运行在调试模式,届时脚本执行的全过程将被展示出来。2. set timeout设置超时时间,计时单位是:秒,timeout -1 为永不超时。
例如:set timeout 30 为设置超时时间为 30 秒。则当某个 expect 判断未能成功匹配的 30 秒后,将跳过该 expect 判断,执行后续内容。3.spawn 它主要的功能是给运行进程加个壳,用来传递交互指令。
spawn 是进入 expect 环境后才可以执行的 expect 内部命令,如果没有装 expect 或者直接在默认的 shell 下执行是找不到 spawn 命令的。
所以不要用 "which spawn" 之类的命令去找 spawn 命令。好比在 windows 里的 dir 就是一个内部命令,这个命令由 shell 自带,你无法找到一个 dir.com 或 dir.exe 的可执行文件。例如:spawn ssh -l username 192.168.1.1 将为 ssh -l username 192.168.1.1 加壳,届时该命令的交互指令将可以被处理。4.expect这里的 expect 是 expect 的一个内部命令,需要在 expect 环境中执行。
该命令用于判断交互中上次输出的结果里是否包含某些字符串,如果有则立即返回。否则如果有设置超时时间,则等待超时时长后返回。例如:expect "password:" 为判别交互输出中是否包含 "password:" 字符串。5.send该命令用于执行交互动作,与手工输入动作等效。
注意: 命令字符串结尾别忘记加上 "\r"(换行符),如果出现异常等待的状态可以核查一下。例如:send "ispass\r" 为交互中输入 "is pass\r"。6.interact执行完成后保持交互状态,把控制权交给控制台,这个时候便可以手工操作。如果没有该命令,命令完成后即退出。7.$argv 参数数组expect 脚本可以接受从 bash 传递过来的参数。
其中通过 [lindex $argv n] 可以获得第 n 个参数的值,通过 [lrange $argv a b] 可以获取 a-b 的参数值。例如:编写 test.sh 脚本,内容如下。#!/usr/bin/expect
set timeout 2                   # 定义脚本中每一条命令的超时2秒后如果没有执行完毕就会自动结束,继续执行下一条命令
set username [lindex $argv 0]           # = bash 脚本中给变量赋值 username=$1
set password [lindex $argv 1]           # = bash 脚本中给变量赋值 password=$2
set hostname [lindex $argv 2]           # = bash 脚本中给变量赋值 hostname=$3
spawn /usr/bin/ssh $username@$hostname # = 在xshell窗口执行命令 ssh mcy@10.0.0.32
expect {                        # 判断交互过程中是否出现字符串,出现了则返回
"yes/no"                      # 指定交互过程中的字符串
{send "yes\r"; exp_continue;} # = 手动输入 yes+回车;继续匹配该 expect 判断语句内的其他项
"Password:"                       # 再次指定 字符串 ,被 expect 判断
{send "$password\r";}         # = 手动输入 密码+回车
}
expect eof则通过调用脚本 ./test.sh mcy password 10.0.0.32 可以使用 mcy 用户以密码 password 登录 10.0.0.32,脚本最后自动登出。8.exp_continueexp_continue 附加于某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句内的其他项。exp_continue 类似于控制语句中的 continue 语句。例如:下例将判断交互输出中是否存在 yes/no 或 *assword。如果匹配 yes/no 则输出 yes 并再次执行判断;如果匹配 *assword 则输出 123abc 并结束该段 expect 语句。expect {\"yes/no\" {send \"yes\r\"; exp_continue;}\"*assword\" {set timeout 300; send \"123abc\r\";}
}注意:exp_continue [-continue_timer] 默认情况下 exp_continue 会重高超时时钟,-continue_timer 选项会阻止时钟重新计数(连续计数)。

expect 与 shell 区别范例

范例来源:https://www.cnblogs.com/kevingrace/p/5900303.html
在做日志分析工具时,发现在屏幕上拿到日志结果会有点慢, expect ssh timeout的设置,这里有个默认时间的问题:expect脚本,首先spawn我们要执行的命令,然后就给出一堆expect的屏幕输出,如果输出匹配了我们的expect{中}的东西,我们就会send一个命令上去,模拟用户输入。但是expect中等待命令的输出信息是有一个timeout的设定的,默认是10秒。这个特性是防止那些执行死机的命令的。一旦到了这个timeout,还是没有屏幕输出的话,expect脚本中下面的代码就会执行。或者我们在expect脚本中如果定义了timeout的响应代码的话,这些代码就会被执行。 解决这样的问题非常简单,最简单的办法就是在expect脚本的开头定义: set timeout -1 -- 没有 timeout 时间
set timeout XX -- 设定 timeout 时间(秒)#####################################   范例1   #####################################
#!/bin/bash/usr/local/bin/expect << EOF
spawn scp -rp -P 22 /opt/kubernetes/server/bin/conf/{k8s-node.yaml,kubelet.kubeconfig} mcy-21:/opt/kubernetes/server/bin/conf/expect {"(yes/no)?"{send "yes\n"expect "password:" { send "$passwd\n" }}
# 上面是第一次登录会提示是否允许,send yes,
# 下面是非第一次提示,直接发送密码"password:"{send "$passwd\n"}
}
expect eof
EOF#####################################   范例2   ######################################从本机自动登录到远程机器192.168.1.200(端口是22,密码是:PASSWORD),登录到远程机器后做以下几个操作:
1. useradd wangshibo
2. mkdir /opt/test
3. exit自动退出
4. 自主决定是否操作其他内容1) 脚本内容如下
vim test-ssh.sh
#!/bin/bash
passwd='PASSWORD'
/usr/local/bin/expect << EOF
set time 30
spawn ssh -p22 root@192.168.1.201
expect {
"*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "$passwd\r" }
}
expect "*#"
send "useradd wangshibo\r"
expect "*#"
send "mkdir /opt/test\r"
expect "*#"
send "exit\r"
interact
expect eof
EOF#####################################   范例3   #####################################
#实现自动登陆目的,登陆机器后不做操作,#使用 bash 脚本
vim test.sh
#!/bin/bash
passwd='PASSWORD'
/usr/local/bin/expect << EOF
set time 30
spawn ssh -p22 root@192.168.1.201
expect {
"*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "$passwd\r" }
}
expect eof
EOF#执行 bash 脚本:
sh test.sh
spawn ssh -p22 root@192.168.1.201
root@192.168.1.201's password:
Last login: Fri Sep 23 16:21:20 2016 from 192.168.1.23#####################################   范例4   ######################################使用 expect 脚本,则写法如下:
vim test
#!/bin/expect
set timeout 30
spawn ssh -p22 root@192.168.1.201
expect "*password:"
send "PASSWORD\r"
interact#执行 expect 脚本:
chmod 755 test
./test需要注意:
spawn后面跟的是操作动作,比如登陆机器后执行uptime,即:
# spawn ssh -p22 root@192.168.1.201 "uptime"#####################################   范例5   #####################################
set timeout -1 永不超时. ~/.bash_profilepasswd='xxx'
expect <<!
set timeout -1
spawn rsync -avH /webapps/Seeyon/A8/base/upload/ root@120.26.93.217:/webapps/Seeyon/A8/base/upload/
expect {"(yes/no)?" {send "yes\n"expect "password:"send "$passwd\n"}"password:" {send "$passwd\n"}
}
expect eof
exit!

shell 脚本范例

免密登陆并免交互推送

简单实现了scp的免交互式脚本和ssh免交互式脚本################################################# scp 场景 #################################################需要将以下源主机上的三个文件拷贝到以下目的主机的对应目录下src host: 192.168.1.1
dist host: 192.168.1.2
files: /root/1/1.txt, /root/2/2.txt, /root/3/3.txt这时候如果手动做的话,将会很繁琐,所以这时候需要一个脚本能够实现文件的自动复制,并且脚本需要自动把密码验证的步骤也覆盖。################################################# ssh 场景 #################################################在任意主机上都可以实现上面将192.168.1.1的上述文件拷贝到192.168.1.2的对应目录下#! /bin/bash
SOURCEHOST=192.168.1.1
DISTHOST=$1
FILE1=/root/1/1.txt
FILE2=/root/2/2.txt
FILE3=/root/3/3.txt
FOLDER1=/root/1/
FOLDER2=/root/2/
FOLDER3=/root/3/
PASSWORD=123456sshpass -p $PASSWORD ssh $SOURCEHOST sshpass -p $PASSWORD scp ${FILE1} ${DISTHOST}${FOLDER1} && sshpass -p $PASSWORD scp ${FILE2} ${DISTHOST}${FOLDER2} && sshpass -p $PASSWORD scp ${FILE3} ${DISTHOST}${FOLDER3}执行脚本:
sh scp.sh 192.168.1.2

shell 脚本中执行脚本

fork # 子 Shell 可以用父 Shell 环境变量,但是父 Shell 中不能用子 Shell 环境变量fork 是最普通的, 就是直接在脚本里面用 path/to/foo.sh 来调用 foo.sh 这个脚本,比如如果是 foo.sh 在当前目录下,就是 ./foo.sh。运行的时候 terminal 会新开一个子 Shell 执行脚本 foo.sh,子 Shell 执行的时候, 父 Shell 还在。子 Shell 执行完毕后返回父 Shell。exec # 子 Shell 可以用父 Shell 环境变量,但是子 shell 执行完毕后就会结束脚本不再执行后面的父 shell 脚本中的内容exec 与 fork 不同,不需要新开一个子 Shell 来执行被调用的脚本. 被调用的脚本与父脚本在同一个 Shell 内执行。但是使用 exec 调用一个新脚本以后, 父脚本中 exec 行之后的内容就不会再执行了。这是 exec 和 source 的区别.source    # 子 Shell 和父 Shell 共用环境变量与 fork 的区别是不新开一个子 Shell 来执行被调用的脚本,而是在同一个 Shell 中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用。# 示例
vim 1.sh
#!/bin/bash
A=2
echo "子脚本中 A=$A"chmod +x 1.shvim test.sh
#!/usr/bin/env bash
A=1
echo "before exec/source/fork: PID for test.sh = $$"
export A
echo "In 1.sh: variable A=$A"
case $1 inexec)echo -e "==> using exec…\n"exec ./1.sh ;;source)echo -e "==> using source…\n"source ./1.sh ;;*)echo -e "==> using fork by default…\n"./1.sh ;;
esac
echo "after exec/source/fork: PID for test.sh = $$"
echo -e "In test.sh: variable A=$A\n"# 测试
sh test.sh
sh test.sh exec
sh test.sh source

01基础 4、Shell 脚本相关推荐

  1. Linux基础篇--shell脚本编程基础

    Linux基础篇–shell脚本编程基础 本章内容概要  编程基础  脚本基本格式  变量  运算  条件测试  配置用户环境 7.1 编程基础 程序:指令+数据 程序编程风格:   过程式:以指令为 ...

  2. 运维与自动化系列③自动化部署基础与shell脚本实现

    自动化部署基础与shell脚本实现 关于自动化的基础知识: 1.1:当前代码部署的实现方式: 运维纯手工scp到web服务器 纯手工登录git服务器执行git pull或svn服务器执行svn upd ...

  3. Linux基础篇–shell脚本编程基础

    本章内容概要  编程基础  脚本基本格式  变量  运算  条件测试  配置用户环境 7.1 编程基础 程序:指令+数据 程序编程风格:   过程式:以指令为中心,数据服务于指令   对象式:以数据为 ...

  4. Linux基础:Shell脚本学习

    一.shell简介 Shell是用户和Unix/Linux内核沟通的桥梁,用户的大部分工作都是通过Shell完成的.Shell既是一种命令语言,又是一种程序设计语言.作为命令语言,它交互式地解释和执行 ...

  5. shell编程(六) : [shell基础] 基本shell脚本

    接上一篇文章Linux shell编程(五): Linux文件权限管理 三.Linux shell 脚本编程基础 了解了Linux系统和命令行的基础知识,是时候开始编程了. 3.1 基本shell脚本 ...

  6. SHELL脚本之基础网络检查

    一.需求说明   作为一名运维工程师,我们经常需要进行系统之间的联调或者系统服务不可用时的故障排查.当出现系统服务无法访问的时候我们需要定位故障原因,可能是网络中断.可能是DNS地址未配置或者配置错误 ...

  7. 标杆徐linux云计算视频,标杆徐2018 Linux自动化运维系列④: Shell脚本自动化编程实战...

    2019年录制SHell新课地址 贴切企业脚本编写思路讲解,带你玩Shell脚本编程实战. 本套课程从实际项目案例出发,近100个Shell实例讲解,由浅入深,循序渐进,带你玩转Shell编程的方方面 ...

  8. 20.2 shell脚本结构和执行

    2019独角兽企业重金招聘Python工程师标准>>> shell脚本结构和执行 开头需要加#!/bin/bash 以#开头的行作为解释说明 脚本的名字以.sh结尾,用于区分这是一个 ...

  9. 一文读懂 shell 脚本编程

    一.shell 脚本基础知识 shell脚本是一个文件,里面存放的是特定格式的指令,系统可以使用脚本解析器翻译或解析指令并执行(无需编译).shell脚本的本质是 shell命令的有序集合 shell ...

  10. shell脚本--判断

    shell编程基础(shell脚本学习笔记) 文章目录 shell编程基础(shell脚本学习笔记) 判断 1. if判断结构 2. if/else判断结构 3. if/elif/else判断结构 4 ...

最新文章

  1. 杭州网络推广浅析网站优化如何更快的提升收录?
  2. 整理find命令输出格式
  3. Flutter 构建一个完整的聊天应用程序
  4. LeetCode Algorithm 6. Z 字形变换
  5. 远控免杀专题(19)-nps_payload免杀
  6. IIS 启动不了(服务没有及时响应启动或控制请求)解决
  7. Spring Boot场景启动器(Starter)
  8. python一行代码迷宫_通过Python代码实现走迷宫的方法
  9. jmeter tps指标在哪里看_性能之路——性能测试连载 (3)-性能指标
  10. vue 如何读取编译携带的参数
  11. 微信小程序picker空白
  12. iOS设计模式解析(三)适配器模式
  13. WebService学习总结(6)——WebService常用接口
  14. 前端常见的安全问题及防范措施
  15. NCBI Genbank核苷酸序列数据库检索基因序列解读
  16. Docker 网络之bridge外部世界如何访问容器
  17. 自定义Drawable 实现图片圆角、圆形、椭圆形
  18. 常见遥感卫星基本参数大全
  19. android H264(3): 流媒体播放器设计方案
  20. 微软最走运/倒霉的十个瞬间

热门文章

  1. 「镁客早报」苹果下调第一财季营收展望;Model 3第四季度交货量不及预期
  2. Android 常用开发框架
  3. 计算机网络校园网课程论文,校园网组建毕业论文
  4. html 页面失去焦点事件,详解HTML onfocus获得焦点和onblur失去焦点事件
  5. 机器人总动员片尾曲歌词_电影歌曲:《机器人总动员》环保主题歌 Down to(
  6. python学习-开篇辞
  7. php好看的图形验证码,一漂亮的PHP图片验证码实例
  8. 候鸟浏览器cookie导入导出清空亚马逊CK号免密登录视频教程(cookie号怎么登录)
  9. 新手如何自学python?
  10. Xposed 实现原理分析