class12 shell编程(四)软件包管理(二)

一、shell编程(四)

1、循环特殊用法

while 循环的特殊用法(遍历文件的每一行):
while read line; do
      循环体
  done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
双小括号方法,即((…))格式,也可以用于算术运算
双小括号方法也可以使bash Shell 实现C语言风格的变量操作    #I=10
    #((I++))
for 循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))do
   循环体done控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

select 循环与菜单

select: select NAME [in WORDS ... ;] do COMMANDS; done       
select variable in list
    do
       循环体命令
    doneselect 循环主要用于创建菜单,按数字顺序排列的示菜单项将显示在标准错误上,并显示PS3提示符,等待用户输入                 
 PS3="would you like ?"用户输入菜单列表中的某个数字,执行相应的命令                    
用户输入被保存在内置变量 REPLY 中。
注意:select循环为死循环
                 
[root@6 cd]# select name in a b c d;do echo "you choose is $name"; done
    1) a
    2) b
    3) c
    4) d
    #? 3
    you choose is c
    #? 2
    you choose is b
    #? 
[root@6 bin]#PS3="would you like ?"  
[root@6 bin]# select name in a b c d;do echo "you choose is $name"; done
1) a
2) b
3) c
4) d
would you like ?2
you choose is b

select与case

select 用是个无限循环,因此要记住用 break  命令退用出循环,或用 exit 按 命令终止脚本。也可以按 ctrl+c退出循环。
break #和continue #;
break #:退出#层循环continue #:跳过#次循环
  select和经常和case联合使用
与 for循环类似,可以省略 in list,此时使用位置参量            
#! /bin/bash PS3="would you like ?"select choose in a b c d;do
 case   $choose in
 a)   echo "THIS IS A PART."
    ;;
 b)   echo "THIS IS B PART."
    ;;
 c)   echo "THIS IS C PART."
    ;;
 d)   echo "THIS IS D PART."
    ;;
 *)    break
    ;; esacdone

2、函数介绍

函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程。   
                        
优先级:alias》函数》内部命令》外部命令
    
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell 程序的一部分。       
函数和shell程序比较相似,区别在于:Shell 程序在子Shell中运行
而Shell函数在当前Shell中运行。因此在当前Shell 中,函数可以对shell 中变量进行修改

定义函数

函数由两部分组成:函数名和函数体。

语法一:    function f_name   {    ... 函数体...
    }
语法二:    function f_name()  {    ... 函数体...
    }
语法三:
    f_name  (){    ... 函数体...
    }

函数使用

函数的定义和使用:

可在交互式环境下定义函数
可将函数放在脚本文件中作为它的一部分
可放在只包含函数的单独文件中

调用:函数只有被调用才会执行;
    调用:给定函数名
    函数名出现的地方,会被自动替换为函数代码
函数的生命周期:被调用时创建,返回时终止

函数返回值

函数有两种返回值:
函数的执行结果返回值:
    (1)使用echo 或printf 命令进行输出
    (2) 函数体中调用命令的输出结果
函数的退出状态码:
    (1)默认取决于函数中执行的最后一条命令的退出状态码
    (2)自定义退出状态码, 其格式为:    return 从函数中返回,用最后状态命令决定返回值    return 0 无错误返回。    return 1-255 有错误 返回

交互式环境下定义和使用函数

示例:    $dir() {
    > ls -l
    > }
定义该函数后,若在$ 后面键入dir ,其显示结果同ls -l的作用相同。    $dir该dir函数将一直保留到用户从系统退出,或执行了如下所示的unset 命令:
    $ unset dir

在脚本中定义及使用函数

函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell 首次发现它后才能使用
调用函数仅使用其函数名即可。
示例:    $cat func1    #!/bin/bash
    # func1
    hello()
    {    echo "Hello there today's date is `date +%F`"
    }    echo "now going to the function hello"
    hello    echo "back from the function"

使用函数文件

可以将经常使用的函数存入函数文件,然后将函数文件载入shell。 

文件名可任意选取,但最好与相关任务有某种联系。例如:functions.main

一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set 命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数。

若要改动函数,首先用unset 命令从shell中删除函数。改动完毕后,再重新载入此文件。

创建函数文件

函数文件示例:    $cat functions.main    #!/bin/bash
    #functions.main
    findit()
    {    if [ $# -lt 1 ] ; then
    echo "Usage:findit file"
    return 1
    fi
    find / -name $1 –print
    }

载入函数

函数文件已创建好后,要将它载入shell

定位 函数文件 并载入shell 的格式:
.  filename 或 source filename

注意:此即< 点> < 空格> < 文件名>这里 的文件名要带正确路径

示例:上例中的函数,可使用 如下命令:
$ . functions.main

检查载入函数

使用set命令检查函数是否已载入。set 命令将在shell中显示所有的载入函数 。

示例:    $set
    findit=( )
    {    if [ $# -lt 1 ]; then
    echo "usage :findit file";    return 1
    fi
    find / -name $1 -print
    }
    …

执行shell 函数

要执行函数,简单地键入函数名即可 :
示例:    $findit groups
    /usr/bin/groups
    /usr/local/backups/groups.bak

删除shell函数

现在对函数做一些改动。首先删除函数,使其对shell 不可用。使用unset 命令完成此 功能.

命令格式为:unset function_name
实例:$unset findit
再键入set 命令,函数将不再 显示

函数参数

函数可以接受参数:
    传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;例如“testfunc arg1 arg2 ...”
    
    在函数体中当中,可使用$1, $2, ...调用这些参数;还可以使用$@, $*, $# 等特殊变量

函数变量

变量作用域:
环境变量:当前shell和子shell 有效
本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数。
           
局部变量:函数的生命周期;函数结束时变量被自动 销毁
               
注意:如果函数中有局部变量,如果其名称同本地变量, 使用局部变量。
           
在函数中定义局部变量的方法     local NAME=VALUE

函数递归实例

函数递归:
    函数直接或间接调用自身
    注意递归层数
    
递归实例:
    阶乘是基斯顿·于 卡曼于 1808 年发明的运算符号,是数学术语
    一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且有0 的阶乘为1 。自然数n 的阶乘写作n!。 。    n!=1 ×2 ×3 ×... ×n。 。
    阶乘亦可以递归方式定义:0!=1 ,n!=(n-1)! ×n。 。    n!=n(n-1)(n-2)...1    n(n-1)! = n(n-1)(n-2)!

函数 递归示例

示例: fact.sh#!/bin/bash#fact() {   if [ $1 -eq 0 -o $1 -eq 1 ]; thenecho 1
   elseecho $[$1*$(fact $[$1-1])]fi}
fact $1

二、软件包管理(二)

包查询

rpm {-q|--query} [select-options] [query-options]
[select-options]
-a:  所有包-f:  查看指定的文件由哪个程序包安装生成[root@6 yum.repos.d]# rpm -qf /bin/rpmrpm-4.8.0-55.el6.x86_64              
-p rpmfile(包名):针对尚未安装的程序包文件做查询操作;  
 [root@6 cd]# rpm -qp /misc/cd/Packages/tree-1.5.3-3.el6.x86_64.rpm 
tree-1.5.3-3.el6.x86_64  
 
--whatprovides CAPABILITY :查询指定的 CAPABILITY由哪个包所提供 [root@6 cd]# rpm -q --whatprovides rpm
  rpm-4.8.0-55.el6.x86_64
 
--whatrequires CAPABILITY :查询指定的 CAPABILITY 被哪个包所依赖  [root@6 cd]# rpm -q --whatrequires rpm
rpm-libs-4.8.0-55.el6.x86_64
man-1.6f-32.el6.x86_64
rpm-python-4.8.0-55.el6.x86_64
yum-3.2.29-73.el6.centos.noarch
policycoreutils-2.0.83-29.el6.x86_64
python-meh-0.12.1-3.el6.noarch
 
rpm2cpio  包文件|cpio –itv 预览包内文件
rpm2cpio  包文件|cpio –id “*.conf” ”  释放包内文件
[root@6 cd]# rpm2cpio /misc/cd/Packages/rpm-4.8.0-55.el6.x86_64.rpm |cpio -id /bin/rpm    ##恢复删除的文件
            
[query-options]
--changelog :查询rpm包的changelog-c: 查询程序的配置文件-d: 查询程序的文档-i: information-l: 查看指定的程序包安装后生成的所有文件;--scripts :程序包自带的脚本片断-R:查询指定的程序包所依赖的CAPABILITY; 
--provides:列出指定程序包所提供的CAPABILITY; 
查询用法:
    -qi PACKAGE, 
    -qf FILE, 
    -qc PACKAGE, 
    -ql PACKAGE, 
    -qd PACKAGE    -qpi PACKAGE_FILE, 
    -qpl PACKAGE_FILE,...    -qa    卸载:
     rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ...


rpm {-V|--verify} [select-options] [verify-options]
    S file Size differs
    M Mode differs (includes permissions and file type)
    5 digest (formerly MD5 sum) differs
    D Device major/minor number mismatch
    L readLink(2) path mismatch
    U User ownership differs
    G Group ownership differs
    T mTime differs
    P capabilities differ

包校验

包来源合法性验正及完整性验正:
    完整性验正:SHA256
    来源合法性验正:RSA
公钥加密:
    对称加密:加密、解密使用同一密钥;
    非对称加密:密钥是成对儿的    public key:  公钥,公开所有人
    secret key:  私钥,  不能公开
导入所需要公钥:
    rpm -K|checksig rpmfile 检查包的完整性和签名
    
     [root@6 cd]# rpm -K /misc/cd/Packages/tree-1.5.3-3.el6.x86_64.rpm 
     /misc/cd/Packages/tree-1.5.3-3.el6.x86_64.rpm: rsa sha1 (md5) pgp md5 OK
     
    rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7        ##导入key文件
    CentOS 7 发行版光盘提供: RPM-GPG-KEY-CentOS-7
    rpm -qa gpg-pubkey*

rpm数据库

数据库重建:
   /var/lib/rpmrpm {--initdb|--rebuilddb}    initdb:  初始化
    如果事先不存在数据库,则新建之
    否则,不执行任何操作
    rebuilddb :重建
    无论当前存在与否,直接重新创建数据库

yum

CentOS: yum, dnfYUM: Yellowdog Update Modifier,rpm的前端程序,用来解决软件包相关依赖性,可以在多个库之间定位软件包,up2date 的替代工具
yum repository: yum repo ,存储了众多rpm 包,以及包的相关的元数据文件(放置于特定目录repodata 下)
   文件服务器:        ftp://
        http://
        file:///

yum 配置文件

yum 客户端配置文件:
    /etc/yum.conf :为所有仓库提供公共配置
    /etc/yum.repos.d/*.repo :为仓库的指向提供配置
    仓库指向的定义:
        [repositoryID]
        name=Some name for this repository
        baseurl=url://path/to/repository/
        enabled={1|0}
        gpgcheck={1|0}
        gpgkey=URL
        enablegroups={1|0}
        failovermethod={roundrobin|priority}
        默认为:roundrobin ,意为随机挑选;
        cost= 默认为1000repo 文件范例
/etc/yum.repo.d/
    [base]
    name=centos 7
    baseurl=http://10.1.0.1/cobbler/ks_mirror/7/
    gpgcheck=1
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentosOS-7
    enabled=1

教学环境yum源

教室里的yum源:http://172.16.0.1/cobbler/ks_mirror/CentOS-X-x86_64/CentOS epel:http://172.16.0.1/fedora-epel/7/x86_64/yum 命令的用法:
yum [options] [command] [package ...]

yum-config-manager

生成172.16.0.1_cobbler_ks_mirror_CentOS-X-x86_64_.repo
yum-config-manager --add-repo=http://172.16.0.1/cobbler/ks_mirror/CentOS-X -x86_64/
yum-config-manager --disable “ 仓库名" 禁用仓库yum-config-manager --enable “ 仓库名”  启用仓库

yum

显示仓库列表:
    repolist [all|enabled|disabled]显示程序包:
  list
    # yum list [all | glob_exp1] [glob_exp2] [...]
    # yum list {available|installed|updates} [glob_exp1]
    [...]安装程序包:
    install package1 [package2] [...]
    reinstall package1 [package2] [...] (重新安装)


升级程序包:
    update [package1] [package2] [...]
    downgrade package1 [package2] [...] ( 降级)
检查可用升级:
    check-update
卸载程序包:
    remove | erase package1 [package2] [...]查看程序包information:
   info [...]查看指定的特性( 可以是某文件) 是由哪个程序包所提供:
   provides | whatprovides feature1 [feature2] [...]清理本地缓存:
   clean [ packages | metadata | expire-cache |rpmdb | plugins | all ]构建缓存:
   makecache
搜索:search string1 [string2] [...]
    以指定的关键字搜索程序包名及summary 信息
查看指定包所依赖的capabilities:
    deplist package1 [package2] [...]查看yum事务历史:
    history [info|list|packages-list|packages-info|
    summary|addon-info|redo|undo|
    rollback|new|sync|stats]
    yum history
    yum history info 6
    yum history undo 6
日志:/var/log/yum.log

积累应用

1 、写 一个服务脚本/root/bin/testsrv.sh ,完成如下要求

(1)  脚本可接受参数:start, stop, restart, status

(2)  如果参数非此四者之一,提示使用格式后报错退出

(3)  如是start:则创建/var/lock/subsys/ SCRIPT_NAME , 并显示“启动成功”考虑:如果事先已经启动过一次,该如何处理?

(4)  如是stop:则删除/var/lock/subsys/ SCRIPT_NAME , 并显示“停止完成”考虑:如果事先已然停止过了,该如何处理?

(5)  如是restart ,则先stop,  再start考虑:如果本来没有start ,如何处理?

(6)  如是status,  则如果/var/lock/subsys/ SCRIPT_NAME 文件存在,则显示“ SCRIPT_NAME is running…”如果/var/lock/subsys/ SCRIPT_NAME 文件不存在,则显示“ SCRIPT_NAMEis stopped…”其中: SCRIPT_NAME 为当前脚 本名

     ###函数
     #! /bin/bash
     servername=SCRIPT_NAME
     START () 
     {  touch  /var/lock/subsys/$servername
         echo  "$servername已启动."
       }
     STOP()
     {  rm -f   /var/lock/subsys/$servername
          echo  "$servername已停止."
     }
 ###程序
 #! /bin/bash
#author:lvasu
#description:
#version:0.1
#date:
source  agrement
PS3="请选择参数:"
servername=SCRIPT_NAME
file=/var/lock/subsys/ $servername
select  agre in  start stop restart status;
do
case  $agre in 
start)   
        if  [ -f  $file ];then
           echo "$servername已开启,不需要启动."
       else 
               START
       fi
           ;;
stop)     
         if  [ -f  $file ];then
              STOP
       else 
             echo "$servername未开启,不需要关闭."
       fi
           ;;
status)   
        if  [ -f  $file ];then
             echo "$servername is running...."
       else 
              echo "$servername is stopped..."
       fi
           ;;
restart)          
                      if  [ -f  $file ];then
              echo "$servername已开启,重启中."
              STOP    &> /dev/null
              START  
           else 
                echo "$servername 未启动,启动中."
                START   
            fi  
           ;;
  *)       
                 echo "你输入的不合法."
                  break
           ;;
  esac
  done
###执行效果
[root@6 bin]# ./testsrv.sh
1) start
2) stop
3) restart
4) status
请选择参数:1
SCRIPT_NAME已启动.
请选择参数:2
SCRIPT_NAME已停止.
请选择参数:3
SCRIPT_NAME 未启动,启动中.
SCRIPT_NAME已启动.
请选择参数:4
SCRIPT_NAME is running....

2 、编写一个脚本/root/bin/copycmd.sh

(1)  提示用户输入一个可执行命令名称;

(2)  获取此命令所依赖到的所有库文件列表

(3)  复制命令至某目标目录( 例如/mnt/sysroot) 下的对应路径下;

如:/bin/bash ==> /mnt/sysroot/bin/bash

/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd

(4)  复制此命令依赖到的所有库文件至目标目录下的对应路径下:

如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-

linux-x86-64.so.2

(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命

令,并重复完成上述功能;直到用户输入quit 退出

###程序
#! /bin/bash
#author:lvasu
#description:
#version:0.1
#date:
while true;do
read -p "请输入一个可执行的命令"  cmd 
addr=/mnt/sysroot
case   $cmd   in  
quit)
        exit
        ;;  
 *)        type $cmd &> /dev/null
           if  [ $? -eq 0 ];then
             which $cmd &> /dev/null 
             if  [ $? -eq 0 ];then
            path=$(which $cmd | sed -rn "/\/.*\/$cmd/p") 
            else  path=/bin/bash
             fi  
             else  echo  "请输入正确的命令."
              continue
            fi
       echo "复制命令的路径:"
       echo $path
       echo '=============================='
       files=$(ldd $path| grep -o '/.*.so.[1-9]') 
       echo "$path的库文件:"
       echo "$files" | tee -a  /testdir/file
       echo '=============================='
       line=$(echo "$files" |wc -l)
       commen1=$(echo $path | sed -nr 's@(^/.*/)[^/]+/?$@\1@p')
       mkdir -p  $addr$commen1 &> /dev/null
       cp  -a $path  $addr$path &> /dev/null
       echo  "$addr$path复制成功."
       echo '=============================='
       while read n;do
          commen2=$(echo $n|sed -nr 's@(^/.*/)[^/]+/?$@\1@p')
           mkdir -p   $addr$commen2 &> /dev/null
          cp -a  $n $addr$commen2   &> /dev/null
           echo "$addr$n复制成功."
        done < /testdir/file 
         rm -f    /testdir/file 
  esac  
done
###执行效果
[root@6 bin]# ./copycmd.sh
请输入一个可执行的命令cd
复制命令的路径:
/bin/bash
==============================
/bin/bash的库文件:
/lib64/libtinfo.so.5
/lib64/libdl.so.2
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
==============================
/mnt/sysroot/bin/bash复制成功.
==============================
/mnt/sysroot/lib64/libtinfo.so.5复制成功.
/mnt/sysroot/lib64/libdl.so.2复制成功.
/mnt/sysroot/lib64/libc.so.6复制成功.
/mnt/sysroot/lib64/ld-linux-x86-64.so.2复制成功.
请输入一个可执行的命令ip
复制命令的路径:
/sbin/ip
==============================
/sbin/ip的库文件:
/lib64/libresolv.so.2
/lib64/libdl.so.2
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
==============================
/mnt/sysroot/sbin/ip复制成功.
==============================
/mnt/sysroot/lib64/libresolv.so.2复制成功.
/mnt/sysroot/lib64/libdl.so.2复制成功.
/mnt/sysroot/lib64/libc.so.6复制成功.
/mnt/sysroot/lib64/ld-linux-x86-64.so.2复制成功.

3 、斐波那契数列又称黄金分割数列,因数学家列昂纳多·斐波那契以兔子

繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0 、1 、1 、2 、3 、5 、8 、13 、21 、34 、……,斐波纳契数列以如下被以递归的

方法定义:F (0 )=0 ,F (1 )=1 ,F (n )=F(n-1)+F(n-2) (n≥2) )

写一个函数,求n 阶斐波那契数列

###函数
tuzi()
{   
       if [ $1 -eq 0 ];then
        echo 0
       elif [ $1 -eq 1 ];then
        echo 1
       else
        echo  $[$(tuzi $[$1-1])+$(tuzi $[$1-2])]
       fi  
}
tuzi2()
{   
     for((i=0;i<=$1;i++))
       if [ $i -eq 0 ];then
        echo 0
       elif [ $i -eq 1 ];then
        echo 1
       else
        echo  $[$(tuzi $[$i-1])+$(tuzi $[$i-2])]
       fi  
    done
}
###程序
#! /bin/bash
#author:lvasu
#description:
#version:0.1
#date:
source  agrement
read -p "请输入斐波那契数列阶数:" n
tuzi $n
echo '==================='
tuzi2 $n
###执行效果
[root@6 bin]# ./feibo.sh
请输入斐波那契数列阶数:10
55
===================
0
1
1
2
3
5
8
13
21
34
55

原创文章,作者:lvasu,如若转载,请注明出处:http://www.178linux.com/38903

(0)
lvasulvasu
上一篇 2016-08-24
下一篇 2016-08-24

相关推荐

  • lvm基本应用

    前言 一种技术要知其然,还要知其所以然 lvm简介 LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制。普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某个文件时,这个文件因为受上层文件系统的限制,也不能跨越多个分区来存放,所以也不能同时放到别的磁盘上…

    Linux干货 2016-05-21
  • chmod 没有执行权限的解决办法 [转载http://www.fblinux.com/?p=30]

    chmod没有权限,貌似就算是root用户也无法授权,这可咋办?chmod是设置权限的命令,但是自身没有了执行权限,那么就表示没有办法更改其他命令的权限,也没有办法改变自己的权限。 1 2 3 4 [root@localhost ~]# ll /bin/chmod ———-. 1 root root 48712 Oct 15 2014 …

    Linux干货 2017-01-01
  • nginx反向代理负载均衡集群配置详解

    反向代理负载均衡集群配置详解 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时站在服务器角度来看,代理服务器对外就表现为一个反向代理服务器。 对反向代理服务器的攻击并不会使得后端内网Web服务器上网页信息遭到…

    Linux干货 2016-11-07
  • 从2个命令简单聊聊CentOS账户锁定原理

    linux中 passwd -l 和usermod -L有什么区别,各自的解锁和锁定原理是什么样的呢?

    2017-11-16
  • linux的发展形成杂谈

    纵观linux的发展,可以看得出Linux是那个时代的产物,是操作系统群雄并起时候的真名天子。从1945年第一台计算机发明开始,人民就开始产生了对操作的系统的需求,首先是单个命令的输入,然后是单批次工作的产生,之后就是多批次流程的产生,然后就是多任务多批次流程,人民一直一直不懈的努力研发一个真正意义上的操作系统。 终于,在70年代,大神级的人物KenThom…

    Linux干货 2016-10-31
  • N22-第八章作业

    1、请描述网桥、集线器、二层交换机、三层交换机、路由器的功能、使用场景与区别。       网桥:网桥是工作在数据链路层的设备。用于将两个LAN连接在一起并按照Mac地址转发数据。网桥保存着所有与它相连的主机的Mac地址表和端口号并具有学习功能。当网桥收到某个数据包后,能根据目的主机的Mac地址再选择从哪个端…

    Linux干货 2016-10-24