分类:shell习题


shell习题-计算器


用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2

 

参考答案:

#!/bin/bash

if [ $# -ne 3 ] 
then
    echo "参数个数不为3"
    echo "当使用乘法时,需要加上脱义符号,例如 $0 1 \* 2"
    exit 1;
fi

num1=`echo $1|sed 's/[0-9.]//g'` ;
if [ -n "$num1" ] 
then
    echo "$1 不是数字" ;
    exit 1
fi

num3=`echo $3|sed 's/[0-9.]//g'` ;
if [ -n "$num3" ]
then
    echo "$3 不是数字" ;
    exit 1
fi

case $2 in
  +)
    echo "scale=2;$1+$3" | bc
    ;;

  -)
    echo "scale=2;$1-$3" | bc 
    ;;

  \*)
    echo "scale=2;$1*$3" | bc 
    ;;

  /)
    echo "scale=2;$1/$3" | bc 
    ;;
 
  *)
   echo  "$2 不是运算符"
   ;;
esac

shell习题-自动添加项目


需求背景:
服务器上,跑的lamp环境,上面有很多客户的项目,每个项目就是一个网站。 由于客户在不断增加,每次增加一个客户,就需要配置相应的mysql、ftp以及httpd. 这种工作是重复性非常强的,所以用脚本实现非常合适。

mysql增加的是对应客户项目的数据库、用户、密码,ftp增加的是对应项目的用户、密码(使用vsftpd,虚拟用户模式),httpd就是要增加虚拟主机配置段。

 

参考答案

#!/bin/bash

webdir=/home/wwwroot
ftpudir=/etc/vsftpd/vuuser
mysqlc="/usr/bin/mysql -uroot -xxxxxx"
httpd_config_f="/usr/local/apache2/conf/extra/httpd-vhosts.conf"

add_mysql_user()
{
        mysql_p=`mkpasswd -s 0 -l 12`
        echo "$pro $mysql_p" >/tmp/$pro.txt
        $mysqlc <<EOF
        grant all on $p.* to "$pro"@'127.0.0.1' identified by "$mysql_p";
EOF
}

add_ftp_user()

{
        ftp_p=`mkpasswd -s 0 -l 12`
        echo "$pro" >> /root/login.txt
        echo "$ftp_p" >> /root/login.txt
        db_load -T -t hash -f /root/login.txt  /etc/vsftpd/vsftpd_login.db
        cd $ftpudir
        cp aaa $pro   //这里的aaa是一个文件,是之前的一个项目,可以作为配置模板
        sed -i "s/aaa/$pro/" $pro  //把里面的aaa改为新的项目名字
        /etc/init.d/vsftpd restart
}

config_httpd()

{
        mkdir $webdir/$pro
        chown vsftpd:vsftpd $webdir/$pro
        echo -e "<VirtualHost *:80> \n     DocumentRoot "/home/internet/www/$pro/" \n     ServerName $dom \n    #ServerAlias \n</VirtualHost> " >> $httpd_config_f
        /usr/local/apache2/bin/apachectl graceful
}

read -p "input the project name: " pro
read -p "input the domain: " dom

add_mysql_user
add_ftp_user
config_httpd

shell习题-获取子进程


说明:本shell题目是一个网友在公众号中提问的,正好利用这个每日习题的机会拿出来让大家一起做一做。

给出一个进程PID,打印出该进程下面的子进程以及子进程下面的所有子进程。(只需要考虑子进程的子进程,再往深层次则不考虑)

 

参考答案:

#!/bin/bash

read -p "please input a pid number: " p
ps -elf > /tmp/ps.log

is_ppid(){
    awk '{print $5}' /tmp/ps.log > /tmp/ps1.log
    if ! grep -qw "$1" /tmp/ps1.log
    then
        echo "PID $1 不是系统进程号,或者它不是父进程"
    return 1
    fi
}

is_ppid $p

if [ $? -eq "1" ]
then
    exit
fi

print_cpid(){
    p=$1
    awk -v p1=$p '$5 == p1 {print $4}' /tmp/ps.log |sort -n |uniq >/tmp/p1.log
    n=`wc -l /tmp/p1.log|awk '{print $1}'`
    if [ $n -ne 0 ]
    then
        echo "PID $p 子进程 pid 如下:"
        cat /tmp/p1.log
    else
    echo "PID $p 没有子进程"
    fi
}

print_cpid $p

for cp in `cat /tmp/p1.log`
do
    print_cpid $cp
done

另外,一条命令查询的方法是:pstree -p pid

shell习题-监控cpu使用率


用shell写一个监控服务器cpu使用率的监控脚本。

思路:用top -bn1 命令,取当前空闲cpu百份比值(只取整数部分),然后用100去剑这个数值。

 

参考答案:

#!/bin/bash

while :
do
    idle=`top -bn1 |sed -n '3p' |awk '{print $5}'|cut -d . -f1`
    use=$[100-$idle]
    if [ $use -gt 90 ]
    then 
        echo "cpu use percent too high."
        #发邮件省略
    fi
    sleep 10
done

shell习题-判断cpu厂商


写一个脚本:
判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor id一行中。
如果其生产商为AuthenticAMD,就显示其为AMD公司;
如果其生产商为GenuineIntel,就显示其为Intel公司;
否则,就说其为非主流公司。

 

参考答案:

#!/bin/bash

m=`cat /proc/cpuinfo |grep vendor_id|awk  -F":" '{print $2}'|tail -1`
if [ $m == "GenuineIntel" ]
then
     echo "cpu is 英特尔"
elif [ $m == "AuthenticAMD" ]
then
     echo "cpu is AMD"
else
     echo "cpu is 非主流"
fi

shell习题-破解字符串


已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果,请破解这些字符串对应的md5sum前的RANDOM对应数字?

21029299
00205d1c
a3da1677
1f6d12dd
890684ba

解题思路:通过每次传递一个参数的方式,来实现依次破解,$RANDOM的范围为0-32767。

参考答案:

#!/bin/bash

for n in {0..32767}
do
        MD5=`echo $n | md5sum | cut -c 1-8`
        if [ "$MD5" == "$1" ];then
            echo "$n $1 "
            break
        fi
done

shell习题-监控节点


一个网站,使用了cdn,全国各地有几十个节点。需要你写一个shell脚本来监控各个节点是否正常。

假如

1 监控的url为www.aming.com/index.php

2 源站ip为88.88.88.88

 

参考答案:

#!/bin/bash

url="www.aming.com/index.php"
s_ip="88.88.88.88"
curl -x $s_ip:80 $url > /tmp/source.html 2>/dev/null

for ip in `cat /tmp/ip.txt`
do
    curl -x $ip:80 $url 2>/dev/null >/tmp/$ip.html
    [ -f /tmp/$ip.diff ] && rm -f /tmp/$ip.diff
    touch /tmp/$ip.diff
    diff /tmp/source.html /tmp/$ip.html > /tmp/$ip.diff 2>/dev/null
    n=`wc -l /tmp/$ip.diff|awk '{print $1}'`
    if [ $n -lt 0 ]
    then
        echo "node $ip sth wrong."
    fi
done

                

shell习题-备份数据表


用shell实现,以并发进程的形式将mysql数据库所有的表备份到当前目录,并把所有的表压缩到一个压缩包文件里。

假设数据库名字为mydb,用户名为aming,密码为passwd。

提示: 在shell中加上&可以将命令丢到后台,从而可以同时执行多条命令达到并发的效果。

 

参考答案:

#!/bin/bash
pre=`date +%F` 
for d in `mysql -uaming -ppasswd mydb -e "show tables"|grep -v 'Tables_in_'`
do
    mysqldump -uaming -ppasswd mydb $d > $d.sql &
done
tar czf $pre.tar.gz *.sql 
rm -f *.sql

shell习题-杀死进程


把当前用户下所有进程名字中含有”aming”的进程关闭。

参考答案:

#!/bin/bash

ps -u $USER |awk '$NF ~ /aming/ {print $1}'|xargs kill

shell习题-a.txt有b.txt没有


有两个文件a.txt和b.txt,需求是,把a.txt中有的并且b.txt中没有的行找出来,并写入到c.txt,然后计算c.txt文件的行数。

参考答案:

#!/bin/bash

n=`wc -l a.txt|awk '{print $1}'`
[ -f c.txt ] && rm -f c.txt
for i in `seq 1 $n`
do
    l=`sed -n "$i"p a.txt`
    if ! grep -q "^$l$" b.txt
    then
    echo $l >>c.txt
    fi
done
wc -l c.txt

或者用grep实现
grep -vwf b.txt a.txt > c.txt; wc -l c.txt