首页 > 代码库 > 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循环/函数