• shell编程-基础


    1.linux 下 Bash 程序开

    1.1 怎样写 shell 脚本

    1.使用编辑工具编辑shell 脚本,例如 vim,脚本名字一般用.sh 为后缀,不用.sh 为后缀 时编辑的内容为全黑,不会有高亮突显命令与变量。
    2.写完后设置脚本的执行权3.执行脚本,做测试,执行方式:./shell-name;bash shell-name ;sh shell-name

    1.2 彩色 shell 的输出

    1.echo -e 可以在控制台输出彩色字符
    2.色彩:
    前背景:30-37
    后背景:40-47
    0:黑 1:红 2:绿 3:黄 4:蓝 5:洋红 6:青 7:白
    3.使用格式:
    33[3X;4ym 同时修改前景和背景颜色
    33[3Xm 只更改前景颜色
    33[4Xm 只更改背景颜色
    33[0m 还原前景和背景颜色,一定要记得还原哦!

    1.3shell 中的变量

    1.变量类型:
    系统变量:由系统本身维护,通常为大写
    自定义变量(UDV):用户创建和维护,通常小写
    2.使用 set 来查看系统变量,$来调用变量
    [root@desktop29 ~]# set
    BASH=/bin/bash
    BASH_ARGC=()
    BASH_ARGV=() …… ……
    3.自定义变量:
    通过“变量名=值”来定义,等号之间没有空格,将右边的值赋给左边的变量,可以定义
    空值,如:mony= ,等号右边没有任何值;mon="" ,引号中没有任何空格
    命名规则:必须以字符或者_开头,不要使用?和*,区分大小写
    4.实例:
    [root@desktop29 ~]# UNAME=liudehua 定义变量
    [root@desktop29 ~]# echo $UNAME 调用变量
    liudehua
    [root@desktop29 ~]# read UNAME 定义变量
    liming
    [root@desktop29 ~]# echo $UNAME
    liming

    1.4echo 命令

    1.使用 echo 命令可以显示文本或变量的值:echo [选项] [字符、变量……]
    2.选项:
    -n 不换行输出,默认就是 echo 一次换一行,用在持续的打印输出
    -e 启用转义字符解析
    a 响铃  退格 c 去除尾部的新行
    换行 回车 水平制表符 \斜杠
    3.实例:
    [root@desktop29 ~]# echo -e "HOST USER 172.24.24.23 $UNAME"
    HOST USER
    172.24.24.23 liming

    1.5shell 中数学计算

    1.语法:expr 操作数 1 运算符 操作数 2(注意中间是要空格的!!)
    2.运算符:+ 加;/除;%取余;* 乘(需要转义)
    3.实例:
    [root@desktop29 ~]# expr 2 + 4
    6
    [root@desktop29 ~]# expr 2 / 4
    0
    [root@desktop29 ~]# UU=$(expr 2 * 100)
    [root@desktop29 ~]# expr $UU / 4
    50
    [root@desktop29 ~]# echo $UU
    200

    1.6 引号的使用

    1.引号:
    "" :双引号,对做转义,对$的变量作解析
    ' ' :单引号,不做任何修
    `` :斜点,用来执行命令
    [root@desktop29 ~]# echo "$UU and date" #不能解读 date 命令,需要$来调用
    200 and date
    [root@desktop29 ~]# echo "$UU and $(date)"
    200 and Wed Oct 5 08:28:42 CST 2011
    [root@desktop29 ~]# echo "$UU and $(date)" #转义了
    200 and $(date)
    [root@desktop29 ~]# echo `$UU and date`
    bash: 200: command not found
    ``斜点不能对$作解析,里面只能使用命令
    [root@desktop29 ~]# echo "$UU and `date`"
    200 and Wed Oct 5 08:29:20 CST 2011
    [root@desktop29 ~]# echo '$UU and date' #不做任何修改
    $UU and date
    [root@desktop29 ~]# echo `date`
    Wed Oct 5 08:30:09 CST 2011
    [root@desktop29 ~]# echo "expr 3 + 4 "
    expr 3 + 4
    [root@desktop29 ~]# echo `expr 3 + 4 ` #先执行 bash
    7
    [root@desktop29 ~]# echo "$(expr 3 + 4 )"
    7

    1.7 退出和退出状态

    1.在 linux 执行指令后,将返回 0:成功 非 0:不成功或有错
    2.通过 echo $?来查看退出状态
    [root@desktop29 ~]# ls /boot/grub/grub.conf
    /boot/grub/grub.conf
    [root@desktop29 ~]# echo $? #命令执行正确,返回 0
    0
    [root@desktop29 ~]# ls /boot/grub/grub.con
    ls: /boot/grub/grub.con: No such file or directory
    [root@desktop29 ~]# echo $? 命令执行不正确,返回非 0
    2

    1.8read 语法

    1.read 作用:获得用户通过键盘输入的数据并保存到变量中
    2.语法:read 变量 1 变量 2 ……
    [root@desktop29 ~]# read TT HH
    tt hh
    [root@desktop29 ~]# echo $TT
    tt
    [root@desktop29 ~]# echo $HH
    hh
    [root@desktop29 ~]# echo "rr ff ss" |while read HH GG II 
    > do
    > echo $HH
    > echo $GG $II
    > done
    rr
    ff ss
    [root@desktop29 ~]# echo $GG #显示是空
    [root@desktop29 ~]#

    1.9 通配符的使用

    1.通配符的意义:
    * :任何的字符出现 0 到多
    ? :任何一个字符
    []:括号内提供的字符选一个
    [ - ]:括号内一段字符
    [^ ]:括号内的都排除掉
    [root@desktop29 ~]# ls /lib/libn*.so
    /lib/libnsl-2.5.so /lib/libnss_hesiod-2.5.so
    /lib/libnss_compat-2.5.so /lib/libnss_ldap-2.5.so
    …… ……
    [root@desktop29 ~]# ls /lib/lib?[abef]*.so
    /lib/libdb-4.3.so /lib/libdevmapper.so
    /lib/libdevmapper-event-lvm2mirror.so /lib/libkeyutils-1.2.so
    /lib/libdevmapper-event-lvm2snapshot.so /lib/libresolv-2.5.so
    /lib/libdevmapper-event.so /lib/libSegFault.so
    [root@desktop29 ~]# ls /lib/lib[^abefnd]*.so
    /lib/libBrokenLocale-2.5.so /lib/libm-2.5.so /lib/libSegFault.so
    /lib/libc-2.5.so /lib/libproc-3.2.7.so /lib/libthread_db-1.0.so
    /lib/libcidn-2.5.so /lib/libpthread-2.5.so /lib/libutil-2.5.so
    /lib/libcrypt-2.5.so /lib/libresolv-2.5.s

    1.10 一行内执行多条命令

    1.语法:命令 1;命令 2;命令 3;……
    [root@desktop29 ~]# echo "ee" >> ff.txt;cp ff.txt d.t;rm ff.txt -f;echo $?
    0
    [root@desktop29 ~]# cat d.t
    ee
    [root@desktop29 ~]# cat ff.txt #被删了
    cat: ff.txt: No such file or directory

    1.11 命令行参数

    参数可以有多个或者没有,如:
    [root@desktop29 ~]# rm d.t -fv #2 个参数
    removed `d.t'
    [root@desktop29 ~]# date #0 个参数
    Wed Oct 5 09:20:15 CST 2011
    特殊的参数:
    -$#保存着命令后面所带的参数的总数
    -$*或-$@将命令后的所有参数作为一个字符串保存
    位置参数:
    $0:命令本身;$1:命令后面的第一个参数;$n:该命令后面的第 n 个参数
    测试位置参数和特殊的参数
    [root@desktop29 ~]# vim dd.sh
    #!/bin/bash
    echo "$0 : $0"
    echo "$1 : $1"
    echo "$2 : $2"
    echo "$# : $#"
    echo "$* : $*"
    [root@desktop29 ~]# chmod u+x dd.sh
    [root@desktop29 ~]# ./dd.sh root redhat
    $0 : ./dd.sh
    $1 : root
    $2 : redhat
    $# : 2
    $* : root redhat

    1.12shell 脚本中条件判断

    1.返回 shell中 0(ture)或 1(flase)结果
    if/then 结构
    2.test 或者[]执行 shell 测试,返回 shell 结果。[]中写入测试条件,注意[空格 测
    试条件 空格]
    3.测试条件:
     
    字符的比较 
    数字的比较
    代表的意思
    == 
    -eq  相等 
    >  
    -gt  大于
    -lt  小于 
    !=
     -ne   不等于
    <=  
    -le  小于等于
    >= 
    -ge  大于等于
    -a:逻辑与,并且;-o:或者,逻辑或
    4.bash2.02 版本以上[[……]]
    5.返回常规编程语言格式的结果
    ((……))和 let……还可以做数字的比较 
    [root@desktop29 ~]# [ "qq" != "cc" ];echo $?
    0
    [root@desktop29 ~]# [ 100 -eq 12 ];echo $?
    1
    [root@desktop29 ~]# echo "100 / ( 5 + 5)" | bc
    10

    1.13 测试文件或文件夹属性 

    1.常见判断
    -a 文件是否存在
    -b 文件是否为块设备
    -d 文件是否为目录
    -s 文件大小是否为 0
    -r 文件是否可读
    -w 文件是否可写
    -x 文件是否可执行
    #man bash 获得更多解释 
    [root@desktop29 /]# touch ff
    [root@desktop29 /]# chmod 111 ff
    [root@desktop29 /]# su - student root #用户则测不出文件的 r,w,x 属性
    [student@desktop29 ~]$ [ -w /ff];echo $?
    1
    [student@desktop29 ~]$ [ -f /ff ];echo $?
    0
    [student@desktop29 ~]$ [ -x /ff ];echo $?
    0
    [student@desktop29 ~]$ [ -d /ff -a -x /ff ];echo $? #-a 是and,非目录,所以为 1
    1
    实例:写一个脚本判断目录下的文件和目录的属性,并打印:
    [student@desktop29 ~]$ cat ds.sh
    #!/bin/bash
    echo -e "please input a doc
    example /etc"
    read DD
    D=directory
    F=file
    for RR in $DD/*
    do
    if [ -d $RR ];then
    if[ -w $RR -a -r $RR -a -x $RR ];then
    echo -e "$RR		$D-rwx"
    else
    if [ -w $RR -a -r $RR ] ;then
    echo -e "$RR		$D-wr"
    else
    if [ -w $RR -a -x $RR ] ;then
    echo -e "$RR		$D-wx"
    else
    if [ -x $RR -a -r $RR ] ;then
    echo -e "$RR		$D-xr"else
    if[ -w $RR ] ;then
    echo -e "$RR		$D-w"
    else
    if [ -r $RR ] ;then
    echo -e "$RR		$D-r"
    else
    if[ -x $RR ] ;then
    echo -e "$RR		$D-x"
    fi
    fi
    fi
    fi
    fi
    fi
    fi
    else
    if [ -f $RR ] ;then
    if [ -w $RR -a -r $RR -a -x $RR ];then
    echo -e "$RR		$F-rwx"
    else
    if[ -w $RR -a -r $RR ] ;then
    echo -e "$RR		$F-wr"
    else
    if [ -w $RR -a -x $RR ] ;then
    echo -e "$RR		$F- wx"
    else
    if [ -x $RR -a -r $RR ] ;then
    echo -e "$RR		$F- xr"
    else
    if[ -w $RR ] ;then
    echo -e "$RR		$F- w"
    else
    if [ -r $RR ] ;then
    echo -e "$RR		$F- r"
    else
    if[ -x $RR ] ;then
    echo -e "$RR		$F- x"
    fi
    fi
    fi
    fi
    fi
    fi
    fi
    fi
    fi
    done

    1.14if……else……fi 

    语法:
    if[判断条件]
    then
    命令 1
    命令 2
    else
    命令 3
    命令 4
    fi 
    实例:依据钱数决定吃快餐或吃 KFC之 if-else-fi 版
    编辑脚本:
    [root@localhost ~]# vim eat.sh
    #!/bin/bash
    echo " money :"
    read FF
    if [ $FF -lt 5 ];then
    echo "fastfood"
    else
    echo "KFC"
    fi
    修改权限
    [root@localhost ~]# chmod u+x eat.sh
    测试
    [root@localhost ~]# ./eat.sh
    money :
    4
    fastfood
    [root@localhost ~]# ./eat.sh
    money :
    6
    KFC

    1.15&&和||以及[[……]] 

    1.&&与运算,||或运算,不能使用在[……]之间,只能使用在[[……]]之间
    2.单独使用,&&代表之前的条件 true 时,||代表之前的条件 false
    3.[[……]]这是一个扩展测试命令,使用该命令可以防止在脚本中出现的逻辑错误信息,如
    &&、||、<和>;在[[……]]可以自动计算十进制和 8/16 进制的值
    1.&&在[]与[[]]之间的区别:
    [root@localhost ~]# [[ -d /tmp && -w /tmp ]];echo $?
    0
    [root@localhost ~]# [ -d /tmp && -w /tmp ];echo $?
    bash: [: missing `]'
    2
    2 依据钱数决定吃快餐或吃 KFC-逻辑符号版
    #!/bin/bash
    echo " money :"
    read FF
    [ $FF -lt 5 ] && echo "fastfood" || echo "KFC"
    测试:
    [root@localhost ~]# ./eat.sh
    money :
    5
    KFC
    [root@localhost ~]# ./eat.sh
    money :
    1
    fastfood

    1.16if 语句的直接使用 

    if 语句可以直接接 shell语句,根据$?判断:
    [root@localhost ~]# cat if_shell.sh
    #!/bin/bash
    D=/etc
    if cd $D &> /dev/null;then #直接接 shell 命令
    echo "now in $D"
    else
    echo "can't change to $D"
    fi
    [root@localhost ~]# ./if_shell.sh
    now in /etc

    1.17if 语句的嵌套 

    实例:菜单项的选择之 if 嵌套版,
    选择1,2,3来显示进入的状态,如果没有输入则打印what do you like?,如果输入的不
    是 1,2,3 中的一个,则打印 please choose:1,2,3 并退出 
    [root@localhost ~]# cat mu.sh
    #!/bin/bash
    echo "please choose:1,2,3"
    echo "1.linux"
    echo "2.win7"
    echo "3.quit"
    read CH
    if [ "$CH" != "" ];then
    if [ $CH -eq 1 ] ;then
    echo " wellcom to linux"
    else
    if [ $CH -eq 2 ];then
    echo "wellcom to win7"
    else
    if [ $CH -eq 3 ];then
    echo "quit"
    else
    echo "please choose 1,2,3"
    fi
    fi
    fi
    else
    echo "what do you like?"
    fi
    测试:
    [root@localhost ~]# ./mu.sh
    please choose:1,2,3
    1.linux
    2.win7
    3.quit
    what do you like?
    [root@localhost ~]# ./mu.sh
    please choose:1,2,3
    1.linux
    2.win7
    3.quit
    1
    wellcom to linux

    1.18if……then……elif 

    多级 if……then……else 可以替换 if 的嵌套使用,直接使用一个或多个测试条件
    将菜单项的选择作修改:
    #!/bin/bash
    echo "please choose:1,2,3"
    echo "1.linux"
    echo "2.win7"
    echo "3.quit"
    read CH
    if [ "$CH" != "" ];then
    if [ $CH -eq 1 ] ;then
    echo " wellcom to linux"
    elif [ $CH -eq 2 ];then
    echo "wellcom to win7"
    elif [ $CH -eq 3 ];then
    echo "quit"
    else
    echo "please choose 1,2,3"
    fi
    else
    echo "what do you like?"
    fi

    1.19exit 退出代码 

    shell脚本执行后如果不成功则会返回一个非0 的值,exit 可以实现脚本退出时返回值,我们可以根据不同的返回值看出是哪个脚本出现问题。 
    实例:如果用户输入的是目录,则返回值为 1,如果不是则返回 4
    #!/bin/bash
    echo -e "input a dir
    example /etc"
    read DD
    if [ -d $DD ];then
    echo " $DD is a directory"
    exit 1
    else
    echo "$DD is not a directory or not exit"
    exit 4
    fi
    测试:
    [root@localhost ~]# ./exit.sh
    input a dir
    example /etc
    /etc
    /etc is a directory
    [root@localhost ~]# echo $?
    1
    [root@localhost ~]# ./exit.sh
    input a dir
    example /etc
    /dd
    /dd is not a directory or not exit
    [root@localhost ~]# echo $?
    4

    1.20  loop 循环 

    1.循环的定义:计算机可以重复的执行特定的指令,知道给定的条件满足为止。
    2.bash 中的循环:for loop ;while loop
    3.注意:
    每个循环使用时,首先用在循环中的变量要在循环之前初始化,然后对每次循环都要对
    条件测试,最后在循环体中执行一次需要对循环测试条件值修改 

    1.21  for loop 

    语法:
    for 变量名 in 列表
    do
    循环体
    done
    列表时一个集合,集合由空格间隔,可以是以下几中:
    数字/字符集合
    1 2 3 6 7
    {1..254}
    文件集合
    /etc/*.conf
    指令结果集合
    $(find /etc -perm -002) 
    实例:
    1.数字集合
    99 乘法表:
    #!/bin/bash
    for A in {1..9}
    do
    for B in {1..9}
    do
    RE=$( expr $A * $B )
    echo " $A * $B = $RE "
    done
    done
    测试:
    [root@localhost ~]# ./9X9.sh
    1 * 1 = 1
    …… ……
    3 * 1 = 3
    …… ……
    9 * 9 = 81
    用脚本编辑 iptables 规则脚本: 
    #!/bin/bash
    echo "#!/bin/bash" >> /bin/setFilewall.sh
    for IP in {1..254}
    do
    echo "iptables -I INPUT -s 192.168.0.$IP -p tcp --dport 80 -j ACCEPT"
    >> /bin/setFilewall.sh
    echo "iptables is making..."
    done
    测试:
    [root@localhost ~]# ./iptables.sh
    iptables is making...
    iptables is making...
    …………
    [root@localhost ~]# tail /bin/setFilewall.sh -n 2
    iptables -I INPUT -s 192.168.0.253 -p tcp --dport 80 -j ACCEPT
    iptables -I INPUT -s 192.168.0.254 -p tcp --dport 80 -j ACCEPT
    2.文件集合 
    for FF in /root/cc/*
    do
    cp $FF $FF.bak -pv
    done
    测试:
    [root@localhost ~]# ./chmod_cc.sh
    `/root/cc/1.cc' -> `/root/cc/1.cc.bak'
    `/root/cc/2.cc' -> `/root/cc/2.cc.bak'
    …… ……
    3.指令集合的实验 
    #!/bin/bash
    for FF in $(find /root/cc -perm +002)
    do
    chmod o-w $FF
    echo "$FF :o-w"
    done

    1.22 for 循环 c 语言格式 

    ((……))不需要使用$来实现对 shell 变量名的调用。特别要注意的是此类语法的逻辑和
    shell截然相反,在(())中,0 代表 false,所有非 0 代表 true 例如:
    1.
    for ((i = 0;i<= 5;i ++))
    do
    echo "welcome $i times "
    done
    建议不要使用在 if-then 中
    2.if(( UID > 0 )) ; then ; echo " Welcome root " ; fI 
    例子:
    国际象棋棋盘:算法(行和列号相加后的结果对 2 取余,为 0 的就是白色块,不为 0 的就
    是黑色块。) 
    #!/bin/bash
    for ((A=1;A<=9;A++)) 等同于 for A in {1..9}
    do
    for ((B=1;B<=9;B++))
    do
    C=$( expr $A + $B )
    D=$( expr $C % 2 ) #取余运算
    if [ $D -eq 0 ];then
    echo -en "33[30;40m 33[0m"
    else
    echo -en "33[37;47m 33[0m"
    fi
    done
    echo -e
    done

    1.23for 循环的练习 

    练习:编辑一个监控服务器的脚本,将信息显示在屏幕上,错误信息记录在日志里: 
    for FF in $(cat /etc/ser.conf | grep -Ev "^(#|$)" )
    do
    #if 后不能用[ping -c2 $FF &> /dev/nul],无论能否 ping 通,返回结果都是非 0
    if ping -c2 $FF &> /dev/nul ;then
    echo "$FF is up..."
    else
    echo "$FF is down..."
    logger "$FF is down ..."
    fi
    done

    1.24while 循环 

    语法:
    while [ 条件测试 ]
    do
    命令
    done
    注意:要修改测试条件的值,防止死循环,可以与 if-then-fi嵌套使用,用 exit 函数退出
    实例: 
    CHOOSE=0
    while [[$CHOOSE != "Q"&& $CHOOSE != "q" ]]
    do
    if (( CHOOSE !="0" )) ; then
    echo -e "Please input 33[33mq 33[0m to quit"
    sleep 4
    fi
    clear
    echo " 1 . Linux "
    echo " 2 . Uni x "
    echo " Q .Qui t "
    read CHOOSE
    echo "Please Input 33[ 33mq 33[0m to quit "
    done
    练习:实现菜单选择,如果选择错误则重新显示菜单,直到选对。 
    #!/bin/bash
    IN=0
    while [ "$IN" != "3" ]
    do
    echo "1.linux"
    echo "2.windows"
    echo "3.quit"
    read IN
    if [ $IN -eq 1 ];then
    echo "wellcom to linux"
    exit 1
    elif [ $IN -eq 2 ];then
    echo "wellcom to windows"
    exit 2
    elif [ $IN -eq 3 ];then
    exit 3
    else #选错了就会清屏后提示 please input 123 并打印菜单
    clear
    echo "please input 123"
    fi
    done

    1.25case 语句 

    case 语句是 if-then-elfi的替代语句 语法:
    case 变量名 in
    匹配 1) 命令;;
    匹配 2) 命令;;
    匹配 3) 命令;; *) 命令;;
    esac
    实例: 
    PIDFIL E=/var/spool /test . pid
    case $1 in
    " start")
    if [ - e $PIDFILE ] ; then
    echo " the testcase has already run"
    else
    echo $$ > $PIDFILE ; echo " starting now. . . "
    fi ;;
    " stop")
    kill -9 $( cat $PIDFILE ) ; rm - f $PIDFILE ; ;
    " status")
    ....
    *) # 默认值, 匹配所有上面没有给定的值
    echo " Usage : /etc/init.d/testcase (start|stop|status) ";;
    esac
    练习:写一个自己的服务,能像其他服务一样用 chkconfig 开启: 
    #!/bin/bash
    #chkconfig: 345 45 67 #这 2 行必须要有才能被 chkconfig 解读
    #description: this is myserver
    case $1 in
    start)
    echo "myserver is started...";;
    stop)
    echo "myserver is stoped...";;
    *) echo " $0 { start|stop}"
    esac
    修改执行权限
    [root@localhost ~]# chmod u+x myserver.sh
    2.复制到/etc/init.d 下,并修改名字
    [root@localhost ~]# cp myserver.sh /etc/init.d/myserver
    测试:
    [root@localhost ~]# chkconfig myserver on
    [root@localhost ~]# chkconfig --list | grep myserver
    myserver 0:off 1:off 2:on 3:on 4:on 5:on 6:off
    [root@localhost ~]# /etc/init.d/myserver start
    myserver is started... 

    1.26 如何调试脚本 

    -v:打印 shell脚本执行的行号
    [root@localhost ~]# bash -v testvx.sh #将整个脚本都展示出来,并执行
    #!/bin/bash
    echo "plese input a number"
    plese input a number
    read N
    3
    R=$( expr $N * $N )
    expr $N * $N
    echo "$N * $N = $R "
    3 * 3 = 9
    -x:对每一个指令作展开计算
    [root@localhost ~]# bash -x testvx.sh #用++与+来区分计算和非计算
    + echo 'plese input a number'
    plese input a number
    + read N
    5 输入
    ++ expr 5 '*' 5
    + R=25
    + echo '5 * 5 = 25 '
    5 * 5 = 25 脚本计算的结果

    1.27 函数的使用 

    函数是一系列的指令或命令
    本身不运行,可以多次调用,简化代码
    语法:
    函数名 ()
    命令 1;命令 2
    return #返回值
    函数的参数:
    函数也可以作为一个程序一样运行,接收参数
    方式:函数名 参数 1 参数 2
    在函数方法体中参数可以用$1、$2 来表示对应的参数 1、参数 2
    实例: 
    max ( )
    {
    if(( $1 > $2 )); then
    return $1 # 注意, 此时函数已经结束了
    fi
    return $2
    }
    max 10 100
    echo $? # 通过 $ ? 取得函数的返回值
    setPath ( )
    {
    PAT H=/bin:/usr/bin
    if (( $UID == 0 )) ; then # 如果为 root
    PATH = $PATH:/usr/bin/sbin:/sbin # 路径追加 sbin 的目录
    fi
    i f (( $2 == "after" )); then # 根据位置参数 2,决定如何添加新路径
    PATH = $PATH:$1 # 在原 PATH 后面追加
    else
    PATH=$1:$PATH # 在原 PATH 之前添加
    fi
    }
    练习 1:结合之前学的语言,使用函数的方式,编写一个菜单选项的脚本,能实现选择菜单
    并执行该菜单的功能:
    #!/bin/bash
    showmanu () #展示菜单的函数
    {
    echo -e "1.linux
    2.windows
    3.quit"
    read IN
    }
    testchoose () #测试用户输入选项的函数
    {
    if [ $IN -eq 1 ] ;then
    echo "wellcom to linux"
    exit 1
    elif [ $IN -eq 2 ] ;then
    echo "wellcom to windows"
    exit 2
    elif [ $IN -eq 3 ] ;then
    exit 3
    else
    clear
    echo "please input 123"
    fi
    }
    main () #当选择错误时,需要循环的显示菜单和测试用户输入的选项
    {
    IN=0
    while [ "$IN" != "3" ]
    do
    showmanu #调用菜单函数
    testchoose #调用测试选项函数
    done
    }
    main #调用函数
    练习 2:在一个脚本中调用其他脚本:
    脚本 1:f.sh
    #!/bin/bash
    echo "---脚本 1---"
    echo "test server..."
    脚本 2:ff.sh
    #!/bin/bash
    [ $# -eq 1 ] && (
    for F in $1/*
    do
    [ -d $F ] && echo "$F is a directory"
    done ) || echo "please input a right directory"
    调用测试脚本:
    #!/bin/bash
    F=/root/f.sh
    FF=/root/ff.sh
    menu ()
    {
    echo -e "1.testServer
    2.findDir
    3.quit"
    }
    main ()
    {
    menu
    read INPUT
    case $INPUT in
    1)
    bash $F
    ;;
    2)
    bash $FF /etc #调用时,可以带参数
    ;;
    3)
    exit -1 ;;
    *)
    clear #清屏
    main #调用 main 函数
    esac
    }
    main

    1.28I/O 重定向和文件描述

    • Linux 经常使用到的 1>,>, &>重定向,各自代表着标准输出,标准错误,以及两者
    都包括(1&&2)
    • Linux 同时除以上的几个重定向外提供给我们0-10 的其他文件描述(File Description:
    FD)
    • 它可以用来对前者的信息做一备份 ,之后再重新调用其信息

    1.29 重定向的高级应用

    >&n 使用系统调用 dup(2)复制文件描述符 n 并把结果用作标准输出;
    <&n 标准输入复制自文件描述符 n;
    <&- 关闭标准输入(键盘);
    >&- 关闭标准输出;
    n<&- 表示将 n 号输入关闭;
    n>&- 表示将 n 号输出关闭;
    上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的
    0 或 1。如:
    . .. 2>file 运行一个命令并把错误输出(文件描述符 2)定向到 file。
    . .. 2>&1 运行一个命令并把它的标准输出和输出合并。(通过复制文件描述符 1 来建立
    文件描述符 2,合并了两个流。)
    2>&1 也就是 FD2=FD1 ,把 FD2 的“数据输出通道” 改为 FD1 的“数据输出通道”。因
    为 FD2 的默认输出和 FD1 的默认输出本来都是 monitor,一样的!
    exec 1>outfilename # 打开文件 outfilename 作为 stdout。
    exec 2>errfilename # 打开文件 errfilename 作为 stderr。
    exec 0<&- # 关闭 FD0。
    exec 1>&- # 关闭 FD1。
    exec 5>&- # 关闭 FD5。
    exec 3>&1; exec 4>&1 #建立FD3; 把 FD3看作最初始的 FD1 的硬盘备份
    ss=$(((ls you no 2>&1 1>&3 3>&-; echo $?>&4)|egrep >file) 4>&1)*exec 3>&-; exec 4>&- #关闭 FD3、FD4。
     
  • 相关阅读:
    云服务器
    发布一个Codesmith 模版,生成Linq 增删除改。看看有什么问题,请大家指点
    标记:今天终于搭建好了SharpDevelop的编译环境
    高效地根据属性名获取某对象的属性值
    如何使用C#操作快捷方式(获取快捷方式属性、创建快捷方式)
    成功编译Chrome浏览器(编译Chromium)
    问题: 某厂部班组有6个人,每周每人都要上5天班,而且每人都要连续休息两天?
    istio Egress Gateway 统一流量出口
    前端笔记
    node: 将json转换ts
  • 原文地址:https://www.cnblogs.com/zoujiaojiao/p/10938109.html
Copyright © 2020-2023  润新知