shell脚本实例(四)

【脚本41】获取ip

提示用户输入网卡的名字,然后我们用脚本输出网卡的ip。 看似简单,但是需要考虑多个方面,比如我们输入的不符合网卡名字的规范,怎么应对。名字符合规范,但是根本就没有这个网卡有怎么应对。

  • 代码参考:
#!/bin/bash
while :
do
     read -p "请输入网卡名: " e
     e1=`echo "$e" | sed 's/[-0-9]//g'`
     e2=`echo "$e" | sed 's/[a-zA-Z]//g'`
     if [ -z $e ]
     then
        echo "你没有输入任何东西"
        continue
     elif [ -z $e1 ]
     then
        echo "不要输入纯数字在centos中网卡名是以eth开头后面加数字"
        continue
     elif [ -z $e2 ]
     then
        echo "不要输入纯字母在centos中网卡名是以eth开头后面加数字"
        continue
     else
        break
     fi
done

ip() {
        ifconfig | grep -A1 "$1 " |tail -1 | awk '{print $2}' | awk -F ":" '{print $2}'
}

myip=`ip $e`
if [ -z $myip ]
then
    echo "抱歉,没有这个网卡。"
else
    echo "你的网卡IP地址是$myip"
fi

【脚本42】列出子目录

  • 脚本的功能:
    脚本可以带参数也可以不带,参数可以有多个,每个参数必须是一个目录,脚本检查参数个数,若等于0,则列出当前目录本身;否则,显示每个参数包含的子目录。

  • 参考代码:

#!/bin/bash
if [ $# == 0 ]
then
    ls -ld `pwd`
else
    for i in `seq 1 $#`
    do
        a=$i
        echo "ls ${!a}"
        ls -l ${!a} |grep '^d'
    done
fi
  • 标注:

你可能会对${!a}有疑问,这里是一个特殊用法,在shell中,$1为第一个参数,$2为第二个参数,以此类推,那么这里的数字要是一个变量如何表示呢?比如n=3,我想取第三个参数,能否写成 $$n? shell中是不支持的,那怎么办? 就用脚本中的这种方法: a=$n, echo ${!a}

【脚本43】下载文件

创建一个函数,能接受两个参数:

第一个参数为URL,即可下载的文件;第二个参数为目录,即下载后保存的位置;
如果用户给的目录不存在,则提示用户是否创建;如果创建就继续执行,否则,函数返回一个51的错误值给调用脚本;
如果给的目录存在,则下载文件;下载命令执行结束后测试文件下载成功与否;如果成功,则>返回0给调用脚本,否则,返回52给调用脚本;
提示,在函数中返回错误值给调用脚本,使用return

  • 参考代码:
#!/bin/bash

if [ ! -d $2 ]
then
    echo "please make directory"
    exit 51
fi

cd $2
wget $1

n=`echo $?`
if [ $n -eq 0 ];then
    exit 0
else
    exit 52
fi

【脚本44】猜数字

写一个猜数字脚本,当用户输入的数字和预设数字(随机生成一个小于100的数字)一样时,直接退出,否则让用户一直输入,并且提示用户的数字比预设数字大或者小。

  • 参考代码:
#!/bin/bash
m=`echo $RANDOM`
n1=$[$m%100]
while :
do
    read -p "Please input a number: " n
    if [ $n == $n1 ]
    then
        break
    elif [ $n -gt $n1 ]
    then
        echo "bigger"
        continue
    else
        echo "smaller"
        continue
    fi
done
echo "You are right."

【脚本45】抽签脚本

  1. 写一个脚本执行后,输入名字,产生随机数01-99之间的数字。
  2. 如果相同的名字重复输入,抓到的数字还是第一次抓取的结果,
  3. 前面已经抓到的数字,下次不能在出现相同数字。
  4. 第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出
    继续等待别的学生输入。
  • 参考代码:
while :
do
    read -p  "Please input a name:" name
    if [ -f /work/test/1.log ];then
    bb=`cat /work/test/1.log | awk -F: '{print $1}' | grep "$name"`

    if [ "$bb" != "$name" ];then  #名字不重复情况下
        aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`
        while :
        do
          dd=`cat  /work/test/1.log |  awk -F: '{print $2}'  | grep "$aa"`
          if [ "$aa"  ==  "$dd" ];then   #数字已经存在情况下
              echo "数字已存在."
              aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`
          else
              break
          fi
        done
        echo "$name:$aa" | tee -a /work/test/1.log
     else
     aa=`cat /work/test/1.log |  grep "$name" | awk -F: '{print $2}'` #名字重复
     echo $aa
     echo "重复名字."
     fi
  else
      aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`
      echo "$name:$aa" | tee -a  /work/test/1.log
  fi
done

【脚本46】打印只有一个数字的行

如题,把一个文本文档中只有一个数字的行给打印出来。

  • 参考代码:
#!/bin/bash

f=/etc/passwd
line=`wc -l $f|awk '{print $1}'`
for l in `seq 1 $line`; do
     n=`sed -n "$l"p $f|grep -o '[0-9]'|wc -l`;
     if [ $n -eq 1 ]; then
        sed -n "$l"p $f
     fi
done

【脚本47】日志归档

类似于日志切割,系统有个logrotate程序,可以完成归档。但现在我们要自己写一个shell脚本实现归档。

  • 举例:
    假如服务的输出日志是1.log,我要求每天归档一个,1.log第二天就变成1.log.1,第三天1.log.2, 第四天 1.log.3 一直到1.log.5

  • 参考答案:

#!/bin/bash

function e_df()
{
    [ -f $1 ] && rm -f $1
}

for i in `seq 5 -1 2`
do
    i2=$[$i-1]
    e_df /data/1.log.$i
    if [ -f /data/1.log.$i2 ]
    then
        mv /data/1.log.$i2 /data/1.log.$i
    fi
done

e_df /data/1.log.1
mv /data/1.log  /data/1.log.1

【脚本48】找出活动ip

写一个shell脚本,把192.168.0.0/24网段在线的ip列出来。

  • 思路:
    for循环, 0.1 — 0.254 依次去ping,能通说明在线。

  • 参考代码:

#!/bin/bash

ips="192.168.1."
for i in `seq 1 254`
do

ping -c 2 $ips$i >/dev/null 2>/dev/null
if [ $? == 0 ]
then
    echo "echo $ips$i is online"
else
    echo "echo $ips$i is not online"
fi
done

【脚本49】检查错误

写一个shell脚本,检查指定的shell脚本是否有语法错误,若有错误,首先显示错误信息,然后提示用户输入q或者Q退出脚本,输入其他内容则直接用vim打开该shell脚本。

  • 提醒:
    检查shell脚本有没有语法错误的命令是 sh -n xxx.sh

  • 参考代码:

#!/bin/bash
sh -n $1 2>/tmp/err
if [ $? -eq "0" ]
then
    echo "The script is OK."
else
    cat /tmp/err
    read -p "Please inpupt Q/q to exit, or others to edit it by vim. " n
    if [ -z $n ]
    then
        vim $1
        exit
    fi
    if [ $n == "q" -o $n == "Q" ]
    then
        exit
    else
        vim $1
        exit
    fi

fi

【脚本50】格式化输出

输入一串随机数字,然后按千分位输出。

比如输入数字串为“123456789”,输出为123,456,789

  • 代码参考:
#!/bin/bash

read -p "输入一串数字:" num
v=`echo $num|sed 's/[0-9]//g'`
if [ -n "$v" ]
then
    echo "请输入纯数字."
    exit
fi
length=${#num}
len=0
sum=''
for i in $(seq 1 $length)
do
        len=$[$len+1]
        if [[ $len == 3 ]]
        then
                sum=','${num:$[0-$i]:1}$sum
                len=0
        else
                sum=${num:$[0-$i]:1}$sum
        fi
done

if [[ -n $(echo $sum | grep '^,' ) ]]
then
        echo ${sum:1}
else
        echo $sum
fi

上面这个实现比较复杂,下面再来一个sed的:

#!/bin/bash
read -p "输入一串数字:" num
v=`echo $num|sed 's/[0-9]//g'`
if [ -n "$v" ]
then
    echo "请输入纯数字."
    exit
fi

echo $num|sed -r '{:number;s/([0-9]+)([0-9]{3})/\1,\2/;t number}'

【脚本51】

  1. 编写一个名为iffile程序,它执行时判断/bin目录下date文件是否存在?
  • 参考代码:
#!/bin/bash
if [ -f /bin/date  ] 
then
    echo "/bin/date file exist."
else
    echo "/bin/date not exist."
fi
  1. 编写一个名为greet的问候程序,它执行时能根据系统当前的时间向用户输出问候信息。设从半夜到中午为早晨,中午到下午六点为下午,下午六点到半夜为晚上。
  • 参考代码:
#!/bin/bash
h=`date +%H`
if [ $h -ge 0 ] && [ $h -lt 12 ]
then
    echo "Good morning."
elif [ $h -ge 12 ] && [ $h -lt 18 ]
then
    echo "Good afternoon."
else
    echo "Good evening."
fi

【脚本52】判断用户登录

  1. 编写一个名为ifuser的程序,它执行时带用户名作为命令行参数,判断该用户是否已经在系统中登录,并给出相关信息。
  • 参考代码:
#!/bin/bash
read -p "Please input the username: " user
if who | grep -qw $user
then
    echo $user is online.
else
    echo $user not online.
fi
  1. 编写一个名为menu的程序,实现简单的弹出式菜单功能,用户能根据显示的菜单项从键盘选择执行对应的命令。
  • 参考代码:
#!/bin/bash
function message()
{
    echo "0\. w"
    echo "1\. ls"
    echo "2.quit"
    read -p "Please input parameter: " Par
}
message
while [ $Par -ne '2' ] ; do
    case $Par in
    0)
        w
        ;;
    1)
        ls
        ;;
    2)
        exit
        ;;
    *)
        echo "Unkown command"
        ;;
  esac
  message
done

【脚本53】更改后缀名

  1. 编写一个名为chname的程序,将当前目录下所有的.txt文件更名为.doc文件。
  • 参考代码:
#!/bin/bash
find . -type f -name "*.txt" > /tmp/txt.list
for f in `cat /tmp/txt.list`
do
    n=`echo $f|sed -r 's/(.*)\.txt/\1/'`
    echo "mv $f $n.doc"
done
  1. 编写一个名为chuser的程序,执行中每隔5分钟检查指定的用户是否登录系统,用户名从命令行输入;如果指定的用户已经登录,则显示相关信息。
  • 参考代码:
#!/bin/bash
read -p "Please input the username: " user
while :
do
    if who | grep -qw $user
    then
        echo $user login.
    else
        echo $user not login.
    fi
    sleep 300
done

【脚本54】判断pid是否一致

先普及一小段知识,我们用ps aux可以查看到进程的PID,而每个PID都会在/proc内产生。如果查看到的pid而proc内是没有的,则是进程被人修改了,这就代表你的系统很有可能已经被*过了。

请大家用上面知识编写一个shell,定期检查下自己的系统是否被人***过。

  • 参考代码:
#!/bin/bash

ps aux|awk '/[0-9]/ {print $2}'|while read pid
do
    result=`find /proc/ -maxdepth 1 -type d -name "$pid"`
    if [ -z $result ]; then
        echo "$pid abnormal!"
    fi
done

【脚本55】一列变三行

比如1.txt内容:

1
2
3
4
5
6
7
处理后应该是:

1 2 3
4 5 6
7
可使用sed命令完成:

sed 'N;N;s/\n/ /g' 1.txt

【脚本56】shell的getops

写一个getinterface.sh 脚本可以接受选项[i,I],完成下面任务:

使用一下形式:getinterface.sh [-i interface | -I ip]
当用户使用-i选项时,显示指定网卡的IP地址;当用户使用-I选项时,显示其指定ip所属的网卡。

  • 例:
    sh getinterface.sh -i eth0
    sh getinterface.sh -I 192.168.0.1

当用户使用除[-i | -I]选项时,显示[-i interface | -I ip]此信息。
当用户指定信息不符合时,显示错误。(比如指定的eth0没有,而是eth1时)

  • 参考代码:
#!/bin/bash

ip add |awk -F ":" '$1 ~ /^[1-9]/ {print $2}'|sed 's/ //g' > /tmp/eths.txt
[ -f /tmp/eth_ip.log ] && rm -f /tmp/eth_ip.log
for eth in `cat /tmp/eths.txt`
do
    ip=`ip add |grep -A2 ": $eth" |grep inet |awk '{print $2}' |cut -d '/' -f 1`
    echo "$eth:$ip" >> /tmp/eth_ip.log
done
useage()
{
    echo "Please useage: $0 -i 网卡名字 or $0 -I ip地址"
}

wrong_eth()
{
    if ! awk -F ':' '{print $1}' /tmp/eth_ip.log | grep -qw "^$1$"
    then
        echo "请指定正确的网卡名字"
        exit
    fi
}

wrong_ip()
{
    if ! awk -F ':' '{print $2}' /tmp/eth_ip.log | grep -qw "^$1$"
    then
        echo "请指定正确的ip地址"
        exit
    fi
}

if [ $# -ne 2 ]
then
    useage
    exit
fi

case $1 in
    -i)
    wrong_eth $2 
    grep -w $2 /tmp/eth_ip.log |awk -F ':' '{print $2}'
    ;;

    -I)
    wrong_ip $2
    grep -w $2 /tmp/eth_ip.log |awk -F ':' '{print $1}'
    ;;

    *)
    useage
    exit
esac

【脚本57】3位随机数字

写一个脚本产生随机3位的数字,并且可以根据用户的输入参数来判断输出几组。 比如,脚本名字为 number3.sh。

  • 执行方法:
bash number3.sh

直接产生一组3位数字。

bash number3.sh 10

插上10组3位数字。

  • 思路:
    可以使用echo $RANDOM获取一个随机数字,然后再除以10,取余获取0-9随机数字,三次运算获得一组。

  • 参考代码:

#!/bin/bash

get_a_num() {
    n=$[$RANDOM%10]
    echo $n
}

get_numbers() {
    for i in 1 2 3; do
        a[$i]=`get_a_num`
    done
    echo ${a[@]}
}

if [ -n "$1" ]; then
    m=`echo $1|sed 's/[0-9]//g'`
    if [ -n "$m" ]; then
        echo "Useage bash $0 n, n is a number, example: bash $0 5"
        exit
    else
        for i in `seq 1 $1`
        do
            get_numbers
        done
    fi
else
    get_numbers

fi

【脚本58】检查服务

先判断是否安装http和mysql,没有安装进行安装,安装了检查是否启动服务,若没有启动则需要启动服务。

  • 说明:
    操作系统为centos6,httpd和mysql全部为rpm包安装。

  • 参考代码:

#!/bin/bash

if_install()
{
    n=`rpm -qa|grep -cw "$1"`
    if [ $n -eq 0 ]
    then
    echo "$1 not install."
    yum install -y $1
    else
    echo "$1 installed."
    fi
}

if_install httpd
if_install mysql-server

chk_ser()
{
    p_n=`ps -C "$1" --no-heading |wc -l`
    if [ $p_n -eq 0 ]
    then
    echo "$1 not start."
    /etc/init.d/$1 start
    else
    echo "$1 started."
    fi
}

chk_httpd
chk_mysqld

   转载规则


《shell脚本实例(四)》 helen 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录