技术源于生活,服务生活 Terry 随笔

Shell脚本入门


Shell简介

Shell是一种应用程序.提供一个界面,用户通过这个界面访问操作系统内核的服务.有很多不同的种类.比如

  • Bourne Shell (/usr/bin/sh, /bin/sh)
  • Bourne Again Shell (/bin/bash)
  • C Shell (/usr/bin/csh)
  • K Shell (/usr/bin/ksh)
  • Shell for Root (/sbin/sh)

Shell脚本 & shell script指以shell编写的脚本程序 Shell编程跟C, PHP, python 编程一样,用你喜欢的文本编辑器写代码,用一个能解释执行的脚本解释器就可以了

本文的Shell脚本都是使用在日常工作中广泛使用的Bash,它是大多数Linux系统默认的Shell

Shell脚本

脚本文件的扩展名默认使用 sh, 扩展名不影响脚本.源代码的第一行一般都是 #!/bin/bash, #!是一个固定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell. 例子:

#!/bin/bash
echo "Hello World"

运行Shell脚本

可以有两种方法:

  • 对sh文件添加可执行权限 chmod +x ./sh1.sh, 然后使用 ./sh1.sh 来执行
  • 直接运行解释器 /bin/sh sh1.sh, 此时脚本文件不需要第一行 #!/bin/bash

与众不同的运算符

算术运算符

运算符 说明 例子
+, -, *, /, % 看符号猜说明 expr $a + $b, 或 $(( a / b ))
== 判断数值是否相等  
!= 判断数值不相等  

关系运算符

只支持数值运算

运算符 说明
-eq 判断是否相等
-ne 不相等
-gt >
-lt <
-ge >=
-le <=

布尔运算符

运算符 说明
! 非运行, [[ ! true ]] 就是 false
-o
-a

逻辑运算

运算符 说明    
&& 逻辑AND    
      逻辑OR

字符串运算符

运算符 说明
= 判断是否相等, [ $a = $b ] 记得中间有空格
!= 判断不相等
-z 判断字符串长度是否为0, (== 0)
-n 判断字符串长度是否不为0 (!= 0)

文件测试运算符

运算符 说明
-b 判断是否为块设备文件, [ -b $file ]
-c 字符设备文件
-d 是否为目录
-f 是否是普通文件
-g 是否设置了SGID位
-k 是否设置了Sticky Bit
-p 是否是有名管道
-u 是否设置了SUID 位
-r 文件是否可读
-w 是否可写
-x 是否可执行
-s 文件不为空
-e 是否存在(包括目录)

一些例子

以下例子支持MAC系统

例子1: 获取本机IP地址,子网掩码,广播地址. 文件下载

#!/bin/sh

# 用于获取本机IP地址,子网掩码,广播地址
#
# 支持参数: 
#   s, -s: 带上表示不要显示说明信息,只显示获取到的信息
# 作者: Terry
# Email: jxd524@163.com
# Data: 2017-06-26 16:19
# 

bSilent=0
while getopts "s" arg ; do
    case $arg in
        s )
            bSilent=1
            ;;
    esac
done

if [[ $bSilent -eq 0 ]]; then
    echo "自动获取本机IP地址, MAC地址"
fi

ipInfo=( $(ifconfig | grep inet | grep netmask | grep broadcast | \
    awk '{                      \
    split($0, ary, " ");        \
    for (i in ary){             \
       if (i % 2 == 0)          \
            print ary[i]        \
    }                           \
}'))
len=`expr ${#ipInfo[@]} / 3`
if [ ${len} == 0 ]; then
    echo "没有找到相关信息"
    exit
fi

_Print() {
    printf "%-20s%-20s%-30s\n" $1 $2 $3
}

if [[ $bSilent -eq 0 ]]; then
   _Print "IP" "MASK" "Broadcast"
fi
i=0
while [[ ${len} > 0 ]]; do
    ip=${ipInfo[$i]}
    let "i += 1"
    mask=${ipInfo[$i]}
    let "i += 1"
    broadcast=${ipInfo[$i]}
    let "i += 1"
    let "len -= 1"
    _Print $ip $mask $broadcast
done

例子2: IP 地址的一些操作,子网掩码的计算等功能. 文件下载

#!/bin/shi


# IP 地址的一些操作,子网掩码的计算等功能
#
# 作者: Terry
# Email: jxd524@163.com
# Data: 2017-06-27 16:19
# 


# 将整数转成IP址
# $1: 整形
# 返回: IP地址
function numToIp()
{
    num=$1
    a=$(( (num & 0xFF000000) >> 24 ))
    b=$(( (num & 0x00FF0000) >> 16 ))
    c=$(( (num & 0x0000FF00) >> 8 ))
    d=$((  num & 0x000000FF ))

    echo "$a.$b.$c.$d"
}

# 将点分十进制的IP转出整形
# $1: 点分十进制的IP
# 返回: IP地址的整形值
function ipToNum()
{
    n=0
    result=($( echo $1 | awk -F "." '{print $1, $2, $3, $4}' ))
    if [[ ${#result[@]} == 4 ]]; then
        n=${result[3]}
        local bit=24
        for (( i = 0; i < 3; i++ )); do
            n=$(( n + (result[i] << bit) ))
            bit=$(( bit - 8))
        done
    fi
    echo $n
}

# 获取子网掩码的整形值
# $1: 支持以下类型
#       1: 16进制, eg 0xFFFFFF00
#       2: IP地址, eg 255.255.255.0
#       3: IP地址+位数 eg 255.255.255.0/24
# 返回: IP地址的整形值
function maskNum()
{
    p=$1
    n16=$( echo $p | grep -i '0x' )
    if [[ ${#n16} != 0 ]]; then
        #0xFFFFFF00
        n=$( printf %d $n16 )
        echo $n
        return
    fi

    nBit=0
    ip=$( echo $p | grep '/' )
    if [[ ${#ip} != 0 ]]; then
        #255.255.255.0/24
        nBit=${p#*/}
        nResult=0

        if [[ $nBit -ge 8 && $nBit -le 30 ]]; then
            i=31
            while [[ $nBit -gt 0 ]]; do
                nResult=$(( nResult + (1 << $i) ))
                nBit=$(( nBit - 1 ))
                i=$(( i - 1 ))
            done
        fi
        echo $nResult
        return
    fi

    echo $(ipToNum $p)
}

# 获取子网掩码的位数
# $1: 整形
# 返回: 几个1, 0表示无效的子网掩码
function maskNumBitCount()
{
    mask=$1
    nBit=0
    i=31
    for (( ; i >= 0; i-- )); do
        if [[ $(( mask & (1 << i) )) != 0 ]]; then
            nBit=$(( nBit + 1 ))
        else
            break
        fi
    done
    for (( ; i >= 0; i-- )); do
        if [[ $(( mask & (1 << i) )) != 0 ]]; then
            echo 0
            return
        fi
    done
    echo $nBit
}

# 获取指定IP,子网掩码下的所有有效IP地址,去掉全0,全1
# $1: IP地址
# $2: 子网掩码
# 返回: IP整形数值
function allIntranetIps()
{
    result=()
    ip=$(ipToNum $1)
    if [[ $ip == 0 ]]; then
        ip=$1
    fi

    mask=$(maskNum $2)
    if [[ $mask == 0 ]]; then
        echo ${result[@]}
        return
    fi

    nBaseIp=$(( ip & mask ))
    nMaskBit=$(maskNumBitCount $mask)
    nHostCount=$(( (1 << (32 - nMaskBit)) - 2 ))
    for (( i = 0; i < $nHostCount; i++ )); do
        result[i]=$(( nBaseIp + i + 1 ))
        #echo $(numToIp $(( nBaseIp + i + 1 )))
    done

    echo ${result[@]}
}

ips=$(allIntranetIps '172.168.80.142' '0xffffff00')
for x in ${ips[@]}; do
    echo $(numToIp $x)
done



相关内容

上一篇 树莓派入门

下一篇 VIM备忘录

Content