shell脚本编程
过程式编程,解释执行,依赖于外部程序文件运行;
脚本是什么:
命令的堆积;
但很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足;
脚本的用途:
自动化常用命令;
执行系统管理和故障排除;
创建简单的应用程序;
处理文本或文件;
编程语言的分类
根据运行方式:
编译运行:源代码-->编译器(编译)-->程序文件
解释运行:源代码-->运行时启动解释器,由解释器边解释边运行
根据其编程过程中功能的实现是调用库还是调用外部的程序文件:
shell脚本编程:
利用系统上的命令及编程组件进行编程;
完整编程:
利用库或编程组件进行编程;
程序编译方式:
动态链接;
静态编译;
根据编程模型:
过程式编程语言;
面向对象的编程语言;
程序=指令+数据
过程式:以指令为中心来组织代码,数据是服务于代码;
顺序执行
选择执行
代码只有一个分支时:条件满足时才执行;(if)
两个或以上的分支,只会执行其中一个满足条件的分支;(case)
循环执行
代表:C,bash
对象式:以数据为中心来组织代码,围绕数据来组织指令;
类(class):实例化对象,method;
代表:java,C++,Python
程序的组成部分:二进制程序文件、库文件、配置文件、帮助文件;
二进制、库文件: 可执行文件;
库文件:不能独立执行,只能被调用时执行;
配置文件、帮助文件:可被查看的文本文件;
《穿越计算机的迷雾》、《量子物理史话》
编程语言的基本结构:
数据存储:变量、数组
表达式:a+b
语句:if
如何编写shell脚本:
第一步:使用文本编辑器来创建文本文件;
文本编辑器:
行编辑器:sed
全屏幕编辑器:nano,vi,vim
第一行顶格:给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件;
常见的解释器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
添加注释,注释以#开头;
缩进
适度添加空白行;
脚本中的空白行会被解释器忽略;
脚本中除了shebang,余下所有以#开头的行都会被视作注释行而被忽略;
第二步:执行脚本:
脚本的运行是通过运行一个子shell进程实现的;
(1)赋予执行权限,并直接运行此程序文件;在命令行上指定脚本的绝对或相对路径;
chmod +x /PATH/TO/SCRIPT_FILE
/PATH/TO/SCRIPT_FILE
对脚本有rx权限;
对脚本所在的目录有rx权限;
(2)直接运行解释器,将脚本作为解释器程序的参数运行;
bash /PATH/TO/SCRIPT_FILE
对脚本有r权限;
对脚本所在的目录有rx权限;
(3)点号用于执行某个脚本,甚至脚本没有可执行权限也可以运行;
如果没有执行权限,用"./"执行就会报权限错误,但是在前面使用点号执行就不会报错;
#. ./99.sh
(4)souce命令也可以读取并在当前环境中执行脚本,同时还返回脚本中最后一个命令的返回状态;
如果没有返回值则为0,代表执行成功;如果执行失败则返回false.
#source 9.sh
1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名、IPv4地址、操作系统版本、内核版本、CPU型号、内存大小、硬盘大小;
vim /root/bin/systeminfo.sh
#!/bin/bash
echo "hostname:`hostname`"
echo "ip address is:`ifconfig eno16777736 | head -2 | tail -1 | tr -s " " | cut -d" " -f3`"
echo "os release version:`cat /etc/centos-release`"
echo "kernel version:`uname -r`"
echo "cpu model:`cat /proc/cpuinfo | grep "model name" | uniq | cut -d: -f2`"
echo "memery size:`cat /proc/meminfo | grep -i "memtotal" | tr -s " " | cut -d: -f2`"
echo "disk size:`fdisk -l /dev/sda | head -2 | tail -1 | cut -d: -f2`"
2、编写脚本/root/bin/backup.sh,可实现将/etc/目录备份到/root/etcYYYY-mm-dd中;
vim /root/bin/backup.sh
#!/bin/bash
cp -a /etc /root/etc`date +%F`
3、编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利用率最大的值;
vim /root/bin/disk.sh
#!/bin/bash
df | tr -s " " | grep "sd" | sort -nr -k5 | head -1 | cut -d" " -f5
4、编写脚本/root/bin/links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数,并按连接数从大到小排序;
vim /root/bin/links.sh
#!/bin/bash
netstat -tan | tr -s " " | cut -d" " -f5 | grep -v ".*[[:alpha:]]\+.*" | uniq -c | sort -r -k1
或者netstat -tan | tr -s " " | cut -d" " -f5 | tail -n +3 | uniq -c | sort -r
5、写一个脚本,实现如下功能:
(1)显示/etc/目录下所有以大写P或小写p开头的文件或目录本身;
(2)显示/var/目录下的所有文件或目录本身,并将显示结果中的小写字幕转换为大写字母后显示;
(3)创建临时文件/tmp/myfile.XXXX;
vim test.sh
#!/bin/bash
ls -d /etc/[Pp]*
ls -d /var/* | tr ‘a-z‘ ‘A-Z‘
mktemp /tmp/myfile.XXXX
chmod +x test.sh
read命令:用户交互;
从键盘读入数据,赋给变量或数组;
read -p "Enter a filename:" FILE
-p ‘promt‘ 给变量赋值;在尝试读取之前,输出PROMPT提示符,并且不换行;
-t TIMEOUT 超时;
-a array 给数组赋值;
read -t 5 -p "Enter a username: " name
[ -z "$name" ] && name="obama"
echo $name
shift:向左移动位置参数;
shift[n]:位置参数轮替;向左移动位置参数;
假设脚本有A,B,C三个参数,那么$1为A,$2为B,$3为C;shift一次之后,$1为B,$2为C;再shift一次后,$1为C...
vim shift.sh
#!/bin/bash
echo "First pos argu: $1"
shift
echo "Second pos argu: $1"
exit:退出本次登录;
在脚本中,exit代表退出当前脚本;可以跟一个数字参数,代表退出状态;
break:
跳出循环;从一个循环(for,while,until,select)中退出;
break后面可以跟一个数字n,代表跳出n层循环,n必须大于1,如果n比当前循环层数还大,则跳出所有循环;
break: only meaningful in a ‘for‘, ‘while‘, or ‘until‘ loop
vim break01.sh
#!/bin/bash
for I in A B C D
do
echo -n "$I:"
for J in `seq 10`
do
if [ $J -eq 5 ];then
break
fi
echo -n " $J"
done
echo
done
当J值为5时,break的输出结果:(循环了4次)
A: 1 2 3 4
B: 1 2 3 4
C: 1 2 3 4
D: 1 2 3 4
vim break02.sh
#!/bin/bash
for I in A B C D
do
echo -n "$I:"
for J in `seq 10`
do
if [ $J -eq 5 ];then
break 2
fi
echo -n " $J"
done
echo
done
echo
当J值为5时,break 2的输出结果:(循环了1次)
A: 1 2 3 4
continue:
结束当前循环而进入下一次循环;
continue后面还可以跟一个数字n,代表跳至外部第n层循环,n必须大于1,如果n比当前循环层数还大,将跳至最外层的循环;
和break不同的是,continue不会终止整个循环体,它只是提前结束本次循环;而整个循环体还将继续执行;
continue: only meaningful in a ‘for‘, ‘while‘, or ‘until‘ loop
vim continue.sh
#!/bin/bash
for I in A B C D
do
echo -n "$I:"
for J in `seq 10`
do
if [ $J -eq 5 ];then
continue
fi
echo -n " $J"
done
echo
done
当J值为5时,continue的输出结果:
A: 1 2 3 4 6 7 8 9 10
B: 1 2 3 4 6 7 8 9 10
C: 1 2 3 4 6 7 8 9 10
D: 1 2 3 4 6 7 8 9 10
vim continue.sh
#!/bin/bash
for I in A B C D
do
echo -n "$I:"
for J in `seq 10`
do
if [ $J -eq 5 ];then
echo
continue 2
fi
echo -n " $J"
done
echo
done
当J值为5时,continue 2的输出结果:
A: 1 2 3 4
B: 1 2 3 4
C: 1 2 3 4
D: 1 2 3 4
#!/bin/bash
while true
do
read -p "Select 1 or 2: " num
echo 1
sleep 1
if [ $num -eq 1 ];then
continue
fi
echo 2
done
#/bin/bash
while true
do
read -p "Select 1 or 2: " num
echo 1
sleep 1
if [ $num -eq 1 ];then
break
fi
echo 2
done
echo 3