首页 > 代码库 > 2016-10-3 linux基础学习——脚本编程之while循环/函数
2016-10-3 linux基础学习——脚本编程之while循环/函数
脚本编程控制结构:
顺序
选择
if
case
循环
for
while
until
1.while Command; do
statment
done
进入循环:条件满足
退出循环:条件不满足
2.until Command; do
statment
..
done
进入循环:条件不满足
退出循环:条件满足
3.for ((expr1; expr2; expr3 )); do
循环体
done
ping
-c #:指定ping几次
-W #:指定ping几秒
awk ‘PATTERN{ACTION}‘ file
-F 指定分隔符
eg:指定以‘:‘为分隔符,查看/etc/passwd文件的第1和最后一个字段
awk -F: ‘{print $1,$NF}‘ /etc/passwd
print $1: 显示第一个字段
print $1,$3: 显示第一/三个字段
print $NF: 显示最后一个字段
1.写一个脚本:
通过ping命令测试192.168.187.120-192.168.187.130之间的所有主机是否在线
如果在线,就显示“ip is up.”,其中的IP要换为真正的IP地址,且以绿色显示;
如果不在线,就显示“ip is down.”,其中的IP要换为真正的IP地址,且以红色显示。
#!/bin/bash
#
IP=192.168.187
for I in `seq 120 130`; do
ping -c 1 -W 1 $IP.$I &> /dev/null && echo -e "\033[32m$IP.$I is up.\033[0m"
|| echo -e "\033[31m$IP.$I is down.\033[0m"
done
2.看前一篇日志
写一个脚本(前提:请为虚拟机新增一块硬盘,假设它为/dev/sdb0),为指定硬盘创建分区
①列出当前系统上所有的硬盘,让用户选择,如果选择quit则退出脚本,
如果用户选择错误,就让用户重新选择
②当用户选择后,提醒用户确认接下来的操作可能会损坏数据,并请用户确认
如果用户选择y就继续,n就退出,否则,让用户重新选择
③抹除那块硬盘上的所有分区,(提示:抹除所有分区后执行sync命令,并让脚本睡眠3s后再分区);
并为其创建三个主分区,第一个为20M,第二个512M,第三位128M(Swap类型),
最后三个分别格式化为ext3,ext3,swap
(提示1:将分区命令通过echo传送给fdisk即可实现,睡眠3s: sleep 3)
(提示2:抹除所有分区dd if=/dev/zero of=/dev/sdb bs=512 count=1)
加分:看有没有挂载,有的话,要先卸载再dd
mount | grep "/dev/sdb" | awk ‘{print $1}‘
单独检验设备有无挂载的小脚本,正文内容放在上一个脚本的抹除分区的dd前即可
#!/bin/bash
#
for I in `mount | grep "/dev/sdb" | awk ‘{print $1}‘`; do
fuser -km $I
umount $I
echo "$I umount OK."
done
break:提前退出循环
continue:提前结束本轮循环,进入下一轮循环
while特殊用法一
while ;do
done
while特殊用法二
while read LINE; do
done < /PATH/TO/SOMEFILE
eg:
写一个脚本, ID号小于505就提前进入循环,判断/etc/passwd文件下的每一行的第7个字段为/bin/bash的,就显示那一行的第一个字段,只显示前6行
#!/bin/bash
#
FILE=/etc/passwd
let I=0
while read LINE; do
# ID号小于505就提前进入循环
[ `echo $LINE | awk -F : ‘{print $3}‘` -le 505 ] && continue
# 判断/etc/passwd文件下的每一行的第7个字段为/bin/bash的,就显示那一行的第一个字段
[ `echo $LINE | awk -F : ‘{print $7}‘` == ‘/bin/bash‘ ] && echo $LINE | awk -F : ‘{print $1}‘ && let I++
# 只显示前6行
[ $I -gt 6 ] && break
done < $FILE
写一个脚本
1.判断一个指定脚本是否有语法错误,如果有错误,则提醒用户键入Q/q无视错误并退出,其它任何键可以通过vim打开这个指定的脚本
2.如果用户通过vim打开编辑后退出是仍然有错误,则重复第一步中的内容,否则就正常关闭退出
./syntax.sh a.sh
提示:bash -n $1
#!/bin/bash
#
until bash -n $1 &> /dev/null; do
read -p "Syntax error,[Q/q] to quit,other for editing:" CHOICE
case $CHOICE in
Q|q)
echo "something wrong,quiting..."
exit 5
;;
*)
vim + $1
;;
esac
done
函数:功能,function
代码重用
写一个脚本,显示一个菜单,d|D显示分区信息,m|M显示memory信息,s|S显示swap信息,选择相应字母就显示对应信息,选错字母就重新打印菜单,直到选择q|Q退出脚本。
#!/bin/bash
#
function SHOWMENU{
cat << EOF
d|D)show disk usage
m|M)show memory usage
s|S)show swap usage
q|Q)quit
EOF
}
read -p "Your choice: " CHOICE
until [ $CHOICE == ‘q‘ -o $CHOICE == ‘Q‘ ]; do
case $CHOICE in
d|D)df -lh ;;
m|M)free -m | grep "^Mem" ;;
s|S)free -m | grep "^Swap" ;;
*)
SHOWMENU
read -p "Your choice,Again: " CHOICE
esac
SHOWMENU
read -p "Your choice: " CHOICE
done
脚本编程之函数 function
结构化编程,不能独立运行,需要调用时执行,可以被多次调用
定义一个函数
格式一:
function FUNCNAME {
command
}
格式二:
FUNCNAME() {
command
}
自定义返回值(0-255)
return #
接收参数的函数:
./a.sh m n
$1:m
$2:n
eg:TWOINT 5 6
$1:5
$2:6
-------查看某用户是否存在,不存在就添加用户并给密码-----
#!/bin/bash
#
ADDUSER(){
if ! id -u $1 &> /dev/null; then ##若用户不存在,就添加用户
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
return 0
else
return 1
fi
}
ADDUSER
if [ $? -eq 0 ]; then
echo "Add user finished."
else
echo "Failure."
fi
-------执行状态结果与执行状态结果的比较--------
#!/bin/bash
#
TWOINT() {
A=9
B=8
C=$[$A+$B]
echo $C
}
#1. $?引用执行状态结果
TWOINT
echo $?
#2. 反引号``代表执行结果
SUM=`TWOINT`
echo $SUM
--------计算10以内依次两个数的和(用主函数参与循环)--------
#!/bin/bash
#
TWOSUM() {
echo $[$1+$2]
}
for I in {1..10}; do
let J=$[$I+1]
echo“$1 plus $J is `TWOSUM $I $J`”
done
--------依次添加user1-10用户并以用户名为密码--------
#!/bin/bash
#
ADDUSER(){
if ! id -u $1 &> /dev/null; then
useradd $1
echo $1 | passwd --stdin $1 &> /dev/null
return 0
else
return 1
fi
}
for I in {1..10}; do
ADDUSER user$I
if [ $? -eq 0 ]; then
echo "Add user$I successful."
else
echo "Add user$I failure."
fi
done
写一个脚本,判定192.168.0.200-192.168.0.254之间的主机哪些在线,要求:
1.使用函数来实现一台主机的判定过程
2.在主程序中来调用此函数判定指定范围内的所有主机的在线情况
版本1:一个函数完成所有主机,主程序调用函数。
#!/bin/bash
#
PING() {
for I in {128..140}; do
if ping 192.168.124.$I &> /dev/null; then
echo "192.168.124.$I is up."
else
echo "192.168.124.$I is down."
fi
done
}
PING
版本2:在主程序中设定具体ping哪些主机,适用范围可广
#!/bin/bash
#
PING() {
if ping -c 1 -w 1 $1 &> /dev/null; then
echo "$I is up."
else
echo "$I is down."
fi
}
for I in {128..135}; do
PING 192.168.124.$I
done
# 如果换一个网段
# for I in {128..135}; do
# PING 192.168.120.$I
# done
版本3:在函数中判断在不在线,但不在函数中显示,
在主函数中显示(添加一个if函数判断,在的话$?为0,显示在在线;为1不在线)
#!/bin/bash
#
PING() {
if ping -c 1 -w 1 $1 &> /dev/null; then
return 0
else
return 1
fi
}
for I in {128..135}; do
PING 192.168.124.$I
if [ $? -eq 0 ]; then
echo -e "\033[31,45m192.168.124.$I is up.\033[0m"
else
echo "192.168.124.$I is down."
fi
done
# for I in {128..135}; do
# PING 192.168.120.$I
# done
写一个脚本:使用函数完成
1.函数能够接受一个参数,参数为用户名
判断一个用户是否存在,如果存在,就返回用户的shell和UID
【grep ^$1 /etc/passwd | cut -d: -f3,7】
, 并返回正常状态值,如果不存在,就说明此用户不存在,并返回错误状态值
2.在主程序中调用函数
扩展1:在主程序中,让用户自己输入用户名,传递给函数来进行判断
扩展2:在主程序中,输入用户名判断后不退出脚本,而是提示用户继续输入写一个用户名;
如果输入的用户不存在,请重新输入一个用户;但如果用户输入的是q/Q就退出脚本
#!/bin/bash
#
TELL() {
if id $1 &> /dev/null; then
echo "`grep ^$1 /etc/passwd | cut -d: -f3,7`"
return 0
else
echo "no $1"
eturn 1
fi
}
read -p "Please input username:" USERNAME
until [ $USERNAME == ‘q‘ -o $USERNAME == ‘Q‘ ]; do
TELL $USERNAME
if [ $? == 0 ]; then
read -p "Please input again:" USERNAME
else
read -p "No $USERNAME, please input again:" USERNAME
fi
done
网络配置
ARP地址解析协议
本地通信,要先广播
交换机--冲突域
路由器--广播域
端口:进程-进程
子网掩码,根据取IP地址
1&任何数=任何数
A类:255.0.0.0 8
0 000 0001 - 0 111 1111
127个A类,127用于回环,1-126
2^7 -1个A类
主机为全0;网络地址
主机位全1:广播地址
容纳2^24-2
B类:255.255.0.0 16
10 00 0000 - 10 11 1111
128-191 64个B类,2^14个B类网
容纳2^16-2
C类:255.255.255.0 24
110 0 0000 - 110 1 1111
192-223 32个C类
容纳2^8-2
D类:
1110 0000 - 1110 1111
224-239
E
私有地址:
A类:10.0.0.0/8
B类:172.16.0.0/16 - 172.31.0.0/16
C类:192.168.0.0/24 - 192.168.255.0/24
路由条目是主机的路由,——主机路由
网络 ——网络路由
源代码-->编译-->链接-->运行
程序:
库
静态
动态
静态链接
动态链接
共享库
配置文件:dir=/path/to/somewhere
程序组成部分:
二进制程序
库
配置文件
帮助文件
/etc,/bin, /sbin, /lib
系统启动就需要用到的程序,这些目录不能挂载额外的分区,必须在根文件系统的分区上
/usr/
bin
sbin
lib
操作系统核心功能,可以单独分区
/usr/local
bin
sbin
lib
etc
man
/opt
/proc
/sys
不能单独分区,默认为空
/dev:设备,不能单独分区
/root:不能单独分区
/var:建议单独分区
/boot:内核,initrd(initramfs)
POST-->BIOS(HD)-->MBR(bootloader)
软件包管理器的核心功能:
1.制作软件包 打包成一文件:二进制程序,库文件,配置文件,帮助文件
2.安装、卸载、升级、查询、校验
生成数据库,跟踪所安装的每一个文件
前端工具:yum, apt-get
后端工具:RPM, dpt
rpm命令:
rpm:
数据库/var/lib/rpm
rpmbuild
安装、卸载、升级、查询、校验、数据库的重建、验证数据包等工作:
rpm命令
包:组成部分
主包:bind-9.7.1.1.e15.i586.rpm
子包:bind-libs-9.7.1.1.e15.i586.rpm
bind-utils-9.7.1.1.e15.i586.rpm
包名格式:name-version-release.arch
主版本号:重大改进
次版本号:某子功能发生重大变化
发行号:修正了部分bug,调整了一点功能
rpm
1.安装
rpm -i /PATH/TO/PACKAGE_FILE
-ih:以#显示进度;每个#表示2%
-iv:显示详细过程
-ivv:更详细过程
-i --nodeps:忽略依赖关系
-i --replacepkgs:重新安装,替换原有安装
-i --force:强行安装,实现重装或降级
2.查询
-q PACKAGE_NAME: 查询指定包是否安装
-qa PACKAGE_NAME:查询已经安装的所有包
-qi: 查询指定包的说明信息
-ql: 查询指定包安装后生成的的文件列表
-qc: 查询指定包安装的配置文件
-qf /PATH/TO/SOMEFILE: 查询指定文件是由哪个rpm包安装生成的
-q --script PACKAGE_NAME:查询指定包的脚步
如果某rpm包尚未安装,我们需查询其说明信息、安装以后会生成的文件:
rpm -qpi /PATH/TO/PACKAGE_FILE 说明信息
-qpf 会生成的文件列表
3.升级
rpm -Uvh /PATH/TO/PACKAGE_FILE: 如果装有老版本的,则升级,否则就安装
-Fvh: 如果装有老版本的,则升级,否则就退出
--oldpackage: 降级
eg:rpm -ivh --oldpackage /PATH/TO/PACKAGE_FILE
4.降级
rpm -e PACKAGE_NAME
--nodeps: 忽略依赖关系
5.校验
rpm -V /PATH/TO/PACKAGE_NAME:检查文件是否被非法改变
6.重建数据库
rpm
--rebuilddb:重建数据库,一定会重新建立
--initdb: 初始化数据库,没有才建立,有就不用建立
7.检验来源合法性,及软件完整性
rpm -K PATH/TO/PACKAGE_FILE
dsa, gpg: 验证来源合法性,也即验证签名,可以使用--nosignature,略过此项
sha1, md5: 验证软件包完整性,可以使用--nodigest,略过此项
加密类型:
对称:加密解密使用同一个密钥
公钥:一对秘钥、公钥、私钥;公钥含与私钥中,可以提取出来,并公开出去
单向
# ls /etc/pki/rpm-gpg/
RPM-GPG-KEY-redhat-release
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release:导入秘钥文件
yum命令
yum仓库中的元数据文件
[root@enrich ~]# mkdir /mnt/cdrom
[root@enrich ~]# mount -r /dev/cdrom /mnt/cdrom/
[root@enrich ~]# cd /mnt/cdrom/Server
[root@enrich Server]# cd repodata/
[root@enrich repodata]# ls
primary.xml.gz
所有RPM包的列表
依赖关系
每个RPM安装生成的文件列表
filelists.xml.gz
当前仓库中所有RPM包的所有文件列表
other.xml.gz
额外信息,RPM包的修改日志
repomd.xml
记录的是上面三个文件的时间戳和校验和
comps*.xml:RPM包分组信息
如何为yum定义repo文件
[Repo_Name]
name=Description
baseurl= //仓库具体路径
ftp://
http://
file://
enabled={1|0}
gpagcheck={1|0}
gpgkey=
yum [options] [command] [package ...]
-y:自动回答为yes
--nogpcheck
list:列表
支持glob
all
available:可用的,仓库中有但尚未安装的
installed:已经安装的
updates:可用的升级
clean:清理缓存
[ packages | metadata | expire-cache | rpmdb | plugins | all ]
repolist:显示repo列表及其简要信息
all
enable:默认
disabled
install:安装
yum install PACKAGE_NAME
update:升级
update_to:升级为指定版本
remove|erase:卸载
info:
provides|whatprovides:查看指定文件或特性是由哪个包安装生成的
groupinfo
grouplist
groupinstall
groupremove
groupupdate
一、使用光盘做yum源
/mnt/cdrom/{Server,VT,Cluster,ClusterStorage}
1.连接电源
2.mkdir /mnt/cdrom
3.mount /dev/cdrom /mnt/cdrom
4.cd /etc/yum.repos.d/
5.ls查看,如果有其他yum源,使其失效
①mv 当前有效yum源的repo文件 增加后缀名.backup
eg:mv server.repo server.repo.backup
②把有效yum源的repo文件下的enable值设为0
6.清除缓存yum clean all
7.vim创建一个光盘yum源.repo文件 cdrom.repo
[Bace]
name=RHEL5 CDROM Server
baseurl=file:///mnt/cdrom/Server
enabled=1
gpgcheck=0
8.刷新yum list all
二、如何创建yum仓库
1.先安装createrepo: yum -y install createrepo
2.mkdir -pV /yum/VT
3.把安装包复制了一份在/yum/VT下: cp /mnt/cdrom/VT/*.rpm /yum/VT/
4.ls /yum/VT
5.cd /etc/yum.repos.d/
6.vim编辑cdrom.repo加入下面这则内容
[VT]
name=VT
baseur1=file:///yum/VT
enable=1
gpgcheck=0
7.yum repolist后,出现VT表示OK
8.创建yum仓库:createrepo /yum/VT/
9.ls /yum/VT可以看到多了一个repodata
10.yum clean all
11.yum repolist
12.cd /mnt/cdrom/VT/repodata————>ls
有个comps-rhe15-vt.xml
13.cp comps-rhe15-vt.xml /root
14.cd
15.createrepo -g /root/comps-rhe15-vt.xml /yum/VT/
本文出自 “11160930” 博客,请务必保留此出处http://11170930.blog.51cto.com/11160930/1858649
2016-10-3 linux基础学习——脚本编程之while循环/函数