day25:判断CPU厂商|监控CPU使用率|打印子进程|LAMP增加项目|简易计算器

原创
2019/01/22 23:06
阅读数 172

1、 判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor id一行中。

如果其生产商为AuthenticAMD,就显示其为AMD公司

如果其生产商为GenuineIntel,就显示其为Intel公司

否则,就说其为非主流公司

分析:可以通过 grep 过滤出包含 "vendor_id" 的这一行,然后用 head -1 打印出第一个(因为如果是多个物理cpu会显示多行),所有只需要第一个就足够了,然后用 awk 以 冒号 为分隔符,打印出第二段;

[root@fenye2019 ~]# grep '^vendor_id' /proc/cpuinfo|head -1
vendor_id    : GenuineIntel
此时再打印如下:前面会有一个分隔符:可以在如下冒号后面 加一个空格;或者用 sed 's# ##g' 把这个空格给过滤掉了;
[root@fenye2019 ~]# grep '^vendor_id' /proc/cpuinfo|head -1|awk -F ': ' '{print $2}'
GenuineIntel
[root@fenye2019 ~]# grep '^vendor_id' /proc/cpuinfo|head -1|awk -F ':' '{print $2}'|sed 's# ##g'
GenuineIntel
接下来就是判断,可以用 if [ $cpu == "AuthenticAMD" ]  then   echo "AMD"  elif  [ $cpu =="GenuineIntel" ] then  echo "inter"  else echo "其他" fi

其实在此处用 case 来说是最合适不过的;

脚本如下:

[root@fenye2019 shell]# cat 66.sh 
#!/bin/bash
cpu=`grep '^vendor_id' /proc/cpuinfo|head -1|awk -F ': ' '{print $2}'`
#if [ $cpu == "AuthenticAMD" ]
#then
#    echo "CPU厂商是AMD"
#elif [ $cpu == "GenuineIntel" ]
#then
#    echo "CPU厂商是Inter"
#else
#    echo "CPU厂商是非主流厂商"
#fi

case $cpu in 
    AuthenticAMD)
        echo "CPU厂商是AMD。"
    ;;
    GenuineIntel)
        echo "CPU厂商是Inter。"
    ;;
    *)
        echo "CPU厂商是其他非主流厂商"
    ;;
esac
执行脚本:
[root@fenye2019 shell]# sh 66.sh 
CPU厂商是Inter。

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

分析:如何查看cpu的使用率,使用 top  -bn1 静态获取top信息;取当前空闲cpu百分比 id(只取整数部分),然后用100去减这个数值;

[root@fenye2019 shell]# top -bn1|grep 'Cpu(s)'
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
[root@fenye2019 shell]# top -bn1|grep 'Cpu(s)'|awk '{print $8}'
88.2

可以打印出空闲 id 百分比cpu值;然后用 100 减去这个空闲值,则是当前cpu的使用率;

[root@fenye2019 shell]# cat 67.sh 
#!/bin/bash
while :
do
    id=`top -bn1|grep 'Cpu(s)'|awk '{print $8}'|cut -d . -f1`
    use=$[100-$id]
    if [ $use -gt 90 ]
    then
        echo "cpu use too high"
        #发邮件内容;
        exit
    else
        echo "CPU 正常"
        exit
    fi
    #sleep 30
done
执行脚本:
[root@fenye2019 shell]# sh 67.sh 
CPU 正常

注释:要运行此脚本的话,可以写到crond里面,也可以开一个screen运行了;

第二种方法:

#!/bin/bash

mail_user=yuanhh@163.com

m_mail() {
    log=$1
    t_s=`date +%s`
    t_s2=`date -d "1 hours ago" +%s`
    if [ ! -f /tmp/$log ]
    then
        #创建$log文件
        touch /tmp/$log 
        #增加a权限,只允许追加内容,不允许更改或删除
        chattr +a /tmp/$log
        #第一次告警,可以直接写入1小时以前的时间戳
        echo $t_s2 >> /tmp/$log
    fi
    #无论$log文件是否是刚刚创建,都需要查看最后一行的时间戳
    t_s2=`tail -1 /tmp/$log|awk '{print $1}'`
    #取出最后一行即上次告警的时间戳后,立即写入当前的时间戳
    echo $t_s>>/tmp/$log
    #取两次时间戳差值
    v=$[$t_s-$t_s2]
    #如果差值超过1800,立即发邮件
    if [ $v -gt 1800 ]
    then
        #发邮件,其中$2为mail函数的第二个参数,这里为一个文件
        python mail.py $mail_user "CPU使用率超过90%" "`top -bn1`"  2>/dev/null   
        #定义计数器临时文件,并写入0         
        echo "0" > /tmp/$log.count
    else
        #如果计数器临时文件不存在,需要创建并写入0
        if [ ! -f /tmp/$log.count ]
        then
            echo "0" > /tmp/$log.count
        fi
        nu=`cat /tmp/$log.count`
        #30分钟内每发生1次告警,计数器加1
        nu2=$[$nu+1]
        echo $nu2>/tmp/$log.count
        #当告警次数超过30次,需要再次发邮件
        if [ $nu2 -gt 30 ]
        then
             python mail.py $mail_user "CPU使用率超过90%持续30分钟了" "`top -bn1`" 2>/dev/null  
             #第二次告警后,将计数器再次从0开始          
             echo "0" > /tmp/$log.count
        fi
    fi
}

while :
do
    cpu_i=`top -bn1 |grep 'Cpu(s):'|sed 's/^%//'|awk -F ' +|%' '{print $8}'`
    cpu_u=`echo 100-$cpu_i|bc`

    if [ $cpu_u -gt 90 ]
    then
       m_mail cpu
    fi
    sleep 60
done

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

其实这个题目可以用一条命令:   pstree  -p  pid   就可以实现;    psmisc (tstree这个包)如下:

pstree  -p    7592  

[root@fenye2019 shell]# pstree -p 7592
sshd(7592)───sshd(29738)───bash(29742)───pstree(30002)

分析:如何查看父进程PPID, 用  ps  -elf 可以打印出那一列;   第四列表示 子进程 PID              第五列则表示 PPID 父进程;

[root@fenye2019 shell]# ps -elf |head 
F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
1 S root         2     0  0  80   0 -     0 kthrea Feb09 ?        00:00:00 [kthreadd]
1 S root         3     2  0  80   0 -     0 smpboo Feb09 ?        00:00:03 [ksoftirqd/0]
1 S root         5     2  0  60 -20 -     0 worker Feb09 ?        00:00:00 [kworker/0:0H]

脚本分析:

首先把ps  -elf 显示的内容写入到一个临时文件/tmp/pid.txt                                  ps  -elf   > /tmp/pid.txt

需要引导用户输入PID:   用 read  -p  " " 传递给一个变量;  p

然后还需要判断一个输入的这个变量是否为空;              if   [ -z $p ]  then    exit  fi

然后用 变量 p  和 临时文件 /tmp/pid.txt 来判断,如果不在,则退出;       if  ! -qw  "$p"  /tmp/pid.txt   then   echo "你输入的pid不存在"  exit   fi

然后写一个函数:用awk -v 传递 shell 的脚本进去, 匹配 pid 等于 第四段,并打印出第五段的内容,写入到一个临时文件;

p=$1  ;  awk -v  p2=$p1  '$5==p2  {print $4}'   > /tmp/$1.txt

然后使用wc  -l  查看行数,如果有则打印出来`cat /tmp/$1.txt`如果没有,则提示用户没有,   n=`wc -l /tmp/$1.txt|awk '{print $1}'`  if  [ $n -ne 0 ] then else fi

因为还需要查看子进程下面的子进程,所有这个函数还需要再调用一次;

脚本内容如下

[root@fenye2019 shell]# cat 68.sh 
#!/bin/bash
ps -efl > /tmp/pid.txt
read -p "pelase input a pid:" p
if [ -z "$p" ]
then 
    echo "你没有输入任何的PID"
    exit
fi
if ! grep -qw "$p" /tmp/pid.txt
then
    echo "你输入的pid不存在"
    exit
fi
pid_c()
{
    p1=$1
    ps -elf|awk -v p2=$p1 '$5==p2 {print $4}' >/tmp/$p1.txt
    n=`wc -l /tmp/$p1.txt|awk '{print $1}'`
    if [ $n -eq 0 ]
    then 
        echo "进程$1下没有pid"
    else
        echo "进程$1下的子进程是:"
        cat /tmp/$p1.txt
    fi
}
pid_c $p
for c_p in `cat /tmp/$p.txt`
do
    pid_c $c_p
done
执行脚本:
[root@fenye2019 shell]# sh 68.sh
pelase input a pid:7592
进程7592下的子进程是:
29738
进程29738下的子进程是:
29742
31544

4需求背景: 服务器上,跑的lamp环境,上面有很多客户的项目,每个项目就是一个网站。 由于客户在不断增加,每次增加一个客户,就需要配置相应的mysql、ftp以及httpd。这种工作重复性非常强的,所以用脚本实现非常合适。mysql增加的是对应客户项目的数据库、用户、密码,ftp增加的是对应项目的用户、密码(使用vsftpd,虚拟用户模式),httpd就是要增加虚拟主机配置段。

分析:其实也不是很难,都是安装操作的命令来写的即可;

脚本可以使用read -p 来引导用户输入;比如域名,项目名字等;

然后需要写三个函数分别实现:增加mysql库,用户名和密码,     增加ftp用户名和密码,                 增加httpd的虚拟主机配置;

[root@fenye2019 shell]# cat 69.sh 
#!/bin/bash
#网站目录
webdir=/data/wwwroot
#ftp的虚拟用户配置文件目录
ftpudir=/etc/vsftpd/vuuser
#ftp虚拟用户密码文件
ftpuserfile=/root/login
#mysql命令行登录root
mysqlc="/usr/local/mysql/bin/mysql -uroot -pjk1hYUcnt6"
#apache虚拟主机配置文件
httpd_config_f="/usr/local/apache2/conf/extra/httpd-vhosts.conf"
#定义增加MySQL库和用户的函数
add_mysql_user()
{
    #生成随机密码
    mysql_p=`mkpasswd -s 0 -l 12`

    #将密码保存到临时文件里,这里的$pro为用户自定义的项目名字
    echo "$pro $mysql_p" >/tmp/$pro.txt

    #这里使用嵌入文档的形式(需顶格),将创建用户并授权的命令传递给mysql    
$mysqlc <<EOF
create database $pro;
grant all on $pro.* to "$pro"@'127.0.0.1' identified by "$mysql_p";
#下面这个EOF必须要顶格
EOF
}
#定义增加FTP用户的函数
add_ftp_user()
{
    ftp_p=`mkpasswd -s 0 -l 12`
    echo "$pro" >> $ftpuserfile
    echo "$ftp_p" >> $ftpuserfile
    #将用户、密码文件转换为密码db文件
    db_load -T -t hash -f $ftpuserfile  /etc/vsftpd/vsftpd_login.db
    cd $ftpudir
    #这里的aaa是一个文件,是之前的一个项目,可以作为配置模板
    cp aaa $pro 
    #把里面的aaa改为新的项目名字
    sed -i "s/aaa/$pro/" $pro 
    #重启vsftpd服务
    /etc/init.d/vsftpd restart
}
#定义增加apache虚拟主机的函数
config_httpd()
{
    #增加网站根目录,和域名保持一致,这里的$dom为用户自定义的域名
    mkdir $webdir/$dom
    #将网站根目录属主和属组设置为ftp用户
    chown vsftpd:vsftpd $webdir/$dom
    #用嵌入文档(需顶格),把虚拟主机配置写入到配置文件里
cat >> $httpd_config_f <<EOF
<VirtualHost *:80>
    DocumentRoot $webdir/$dom
    ServerName $dom
    <Directory $webdir/$dom>
        AllowOverride none
        Require all granted  
    </Directory>
</VirtualHost>
EOF
    #重载apache服务
    /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

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

分析:根据题意,脚本有三个参数:所以首先要判断用户输入的参数个数是否符合要求:     if  [ $#  -ne 3 ] then  echo " " exit     fi

还需要判断:第一个和第三个参数是数字,可以是小数,当不能是负数,可以用 sed 来过滤下:  写成函数最合适(多次调用)

n=`echo $1|sed 's#[0-9.]##g'`               #用 sed 把数字替换掉,如果还有字符,则肯定不是合法数字; 

n1=`echo $1|sed 's#[^.]##g'`             #用 sed 把点的特殊字符过滤掉,然后判断长度,如果还有,则也不合法;

if [ -n "$n" ] || [ "$n1" -gt 1 ]       then    echo "  "   exit    fi

然后使用 case 来判断第二列 + -  *   /   即可;   注意: * 会和 case 原有语法冲突,需要使用脱义字符;

 脚本代码如下:

[root@fenye2019 shell]# cat 70.sh 
#!/bin/bash
if [ $# -ne 3 ]
then
    echo "脚本参数不是三个"
    exit
fi
if_number()
{
   n1=`echo $1|sed 's#[0-9.]##g'`
   if [ -n "$n1" ]
   then
       echo "$1不是数字"
       exit
   fi
   if echo $1|grep -q '^\.'
   then
       echo "数字$1不合法"
   fi
}
if_number $1
if_number $3
case $2 in 
    +)
      echo "$1+$3"|bc
       ;;
   -)
      echo "$1-$3"|bc
       ;;
   \*)
      echo "$1*$3"|bc
       ;;
    /)
      echo "scale=2;$1/$3"|bc
      ;;
    *)
      echo "你输入的格式不对,第二个参数只能是+,-,*,/"
      ;;
esac
执行脚本:
[root@fenye2019 shell]# sh 70.sh 5 + 6
11
[root@fenye2019 shell]# sh 70.sh 5 - 6
-1
[root@fenye2019 shell]# sh 70.sh 5 / 6
.83
[root@fenye2019 shell]# sh 70.sh 5 * 6
脚本参数不是三个
[root@fenye2019 shell]# sh 70.sh 5 \* 6
30
[root@fenye2019 shell]# sh 70.sh 5 '*' 6
30

注释:如下执行过程,当执行 的时候,会出现错误,因为在脚本中 * 表示所有符号;会有问题;

如果要正常执行,则需要在运行时加上脱义符号或者单引号即可;

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部