2016年3月

linux的cpu和磁盘io优先级设置

在服务器上常常会运行一些备份脚本,当备份的文件比较多时,会占用大量的cpu和磁盘io。为了不影响生产业务,应尽量减少这些脚本运行时使用的cpu和磁盘io。通常linux下限制cpu使用有三种方法:

  1. nice/renice : 调整进程使用cpu的优先级
  2. cpulimit :不修改进程的nice值,通过暂停进程一段时间,来限制cpu使用
  3. cgroups :内核提供的机制,可以限制、记录、隔离一组进程所使用的cpu、内存、磁盘、网络等资源,是docker等容器的基础技术之一

限制磁盘io :

  1. ionice : 调整io调度的优先级
  2. cgroups

这里只说nice和ionice,实际上nice和ionice只是改变优先级,并没有真正的限制

一、nice

1.1 进程优先级

要理解nice值,首先要说明一下优先级的概念,先来看一下进程的信息:

[root@nixops.me ~]# ps -efl
F S UID         PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
5 S asterisk  5319  1607  -5  80   0 - 119325 ep_pol Mar23 ?       00:03:55 /usr/sbin/httpd
  • PRI 指进程优先级,优先级小的进程会获得比较多的CPU时间,程序就会被优先处理
  • NI 即为nice值
  • 两者关系为 :PRI(new)=PRI(default)+nice

其中nice值可以用户指定,nice的默认值为0,root可用范围从-20到19,普通用户只能用0到19,值越小PRI(new)越小,CPU执行优先级越高。同时可以知道:只有root能提高优先级,普通用户只能降低优先级。

1.2 设置程序启动时的优先级

nice 只有一个参数 : -n,启动程序时指定优先级:

nice -n -20  /opt/backup.sh  #优先级最高
nice -n 19  /opt/backup.sh   #优先级最低

1.3 设置程序运行时的优先级

对于已经在运行的程序,如果需要调整优先级,需要用renice命令,设置正在运行程序nice的值为15:

[root@nixops.me ~]# renice -n +15 5319 

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
5 S asterisk  5319  1607  -5  95  15  - 119325 ep_pol Mar23 ?       00:03:55 /usr/sbin/httpd

root用户可以为其它用户或组设置nice值:

[root@nixops.me ~]# renice -n +15 -u zabbix   #设置zabbix用户的所有进程nice值为15
[root@nixops.me ~]# renice -n +15 -u zabbix   #设置zabbix用户的所有进程nice值为15

还可以为进程组设置nice值,查看进程组:


[root@nixops.me ~]# ps -efj 
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
asterisk  5296  1607  1607  1607  0 Mar23 ?        00:03:54 /usr/sbin/httpd
asterisk  5319  1607  1607  1607  0 Mar23 ?        00:03:55 /usr/sbin/httpd
asterisk  5394  1607  1607  1607  0 Mar23 ?        00:03:55 /usr/sbin/httpd

apache的进程组(PGID)为:1607,设置nice值为-8:

[root@nixops.me ~]# renice  -n -8 -g 1607

二、ionice

linux默认IO调度器使用CFQ调度算法,支持用ionice命令为程序指定io调度策略和优先级,IO调度策略分为三种:

  • Idle :其他进程没有磁盘IO时,才进行磁盘IO
  • Best Effort:缺省调度策略,可以设置0-7的优先级,数值越小优先级越高,同优先级的进程采用round-robin算法调度;
  • Real Time :立即访问磁盘,无视其它进程IO
  • None 即Best Effort,进程未指定策略和优先级时显示为none,会使用依据cpu nice设置计算出优先级

策略 :0 - none, 1 - Real Time, 2 - Best Effort, 3 - idle

使用idle策略:

ionice -c 3 -p 进程id

使用Real Time策略:

ionice -c 1  -p 进程id

使用Best Effort策略,并指定优先级最低:

ionice -c 2 -n 7 -p 进程id

三、同时限制cpu和磁盘io的优先级
为了对生产环境造成影响最小,设置备份脚本运行时,cpu和磁盘io的优先级都最低:

nice -n 19 ionice -c2 -n7  /bin/sh /opt/backup.sh

参考文章:
https://linux.cn/article-4742-1.html
http://www.linuxde.net/2013/06/13933.html

使用python模拟网站登录和识别验证码

我们有几个产品访问量比较大,所用的短信和voip服务消耗非常快,为了不影响业务,老大要求运维每天要检查供应商的余额并登记,账号有十几个,查起来非常烦。听说真正的geek重复两遍以上的操作都会写脚本完成,我这个小菜鸟也不自量力一下,写个脚本模拟账号登录和查额,验证码识别等,这篇博客做个备忘,人生苦短,当然用python啦!

比较难搞定的是验证码识别,用的是pytesseract,默认没有training对验证码识别不高,但好在验证码比较简单,写个循环一直拿验证码,直到识别出来:

#!/usr/bin/env python 
# -*- coding: UTF-8 -*-

import pytesseract
from PIL import Image,ImageFile,ImageEnhance
ImageFile.LOAD_TRUNCATED_IMAGES = True
'''
Dependencies List :
   1: yum install tesseract tesseract-devel -y
   2: yum install libjpeg libjpeg-devel -y
   3: pip install requests
   4: pip install pytesseract
   5: pip install pillow
   6: pip install tesseract-ocr
 '''
 
def get_captcha(self):

    api_captcha = 'http://sms.nixops.me/main/GetCode.asp'
    get_headers = {

            'Host' : 'sms.nixops.me',
            'Cache-Control':'max-age=0',
            'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Upgrade-Insecure-Requests' : '1',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
            'Referer': 'http://sms.nixops.me/index.asp',
            'Accept-Encoding' : 'gzip, deflate,sdch',
            'Accept-Language ' : 'zh-CN,zh;q=0.8',
            'Connection': 'close',

    }

    while True:
        r = requests.get(api_captcha,timeout=5,headers=get_headers)
        with open('captcha.jpg','wb') as f:
            for chunk in r.iter_content(1024):
                f.write(chunk)

        img = Image.open('captcha.jpg')
        text = pytesseract.image_to_string(img)
        text = text.strip()
        #确保识别到的是4位数字
        if len(text) == 4:
            try:
                int(text)
            except:
                pass
            else:
                break

    return text,r.cookies
    

识别到验证码会返回识别结果和cookies,用这个cookies和验证码一起登录才行,否则就会报验证码不符。登录是使用requests库,好处是不用手动处理cookies,非常简单:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__author__='will@nixops.me'
import requests
''' pip install requests'''

def login(self):

    start = requests.session()
    login = start.post(url_login,data=postdata,headers=post_headers,cookies=post_cookies,params=url_params)
    
    while True :
        start = requests.session()
        login = start.post(api_login,data=postdata,params=url_params,headers=post_headers,cookies=get_data[1])
        #判断登录是否拿到登录后的cookies,确保登录成功
        if len(start.cookies) == 7:
            return start.cookies
            break

    bal = start.get(api_balance)
.....

总的来说,还是非常简单的,完整代码就不贴了

bash记录所有用户的历史记录

bash是多数Linux发行版默认的shell,虽然不及zsh好用,但比其它的shell好太多。
我们的生产服务器很多,没有用跳板机,又是多人共用root用户,为了审计用户操作,需要记录执行命令的用户、时间和ip等信息。本文之所以要优化,主要是因为bash默认配置存在以下几点不足:

  1. 历史记录保存数目有限,默认1000条
  2. 记录不详细,不记录命令执行时间/执行用户名/用户ip等
  3. 历史记录会丢失,主要有两种情况: 1. bash异常退出 2.同一用户多处登录或开了多个会话,只会记录最后退出的会话历史

上面这三点不足,都可以通过调整bashrc的参数解决,怎么做就不说了。服务器这么多,如何用最省事方法解决才是关键。我采用的是用syslog记录bash历史命令

一、常规配置syslog做法

1.1 配置全局bash历史记录格式
编辑/etc/bashrc(centos)或/etc/bash.bashrc(debian),增加:

export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$(who am i) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"'

1.2 配置rsyslog
新增文件/etc/rsyslog.d/bash.conf,内容:

local6.*    /var/log/bash_history.log

重启rsyslog :

service rsyslog restart

1.3 配置日志分割
虽然bash历史记录不会占用太多空间,但为了方便查看还是用logrotate分割一下。,按天切分日志,新建文件/opt/logrotate_bash.conf,内容:

/var/log/bash_history.log
  {
   sharedscripts
   postrotate
   /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
  endscript
}

添加定时任务:

59 23 *  *  * root /usr/sbin/logrotate -f /opt/logrotate_bash.conf

如果不介意两天的日志混在一起,可以直接将/var/log/bash_history.log加入/etc/logrotate.d/syslog中即可。

二、使用logger命令记录到syslog

服务器这么多,这样配置有些麻烦,能不能更简单一点,答案是可以的。logger命令是一个shell接口,可以通过它使用Syslog日志系统。直接编辑/etc/profile文件,在最后加入:

    function log2syslog
    {
export HISTTIMEFORMAT="[%Y-%m-%d %H:%M:%S] [`who am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`] "
export PROMPT_COMMAND='\
  if [ -z "$OLD_PWD" ];then
        export OLD_PWD=$(pwd);
  fi;
  if [ ! -z "$LAST_CMD" ] && [ "$(history 1)" != "$LAST_CMD" ]; then
        logger  `whoami`_shell_cmd "[$OLD_PWD]$(history 1)";
  fi ;
  export LAST_CMD="$(history 1)";
  export OLD_PWD=$(pwd);'
}    
trap log2syslog DEBUG

即可将bash的历史记录打入/var/log/message中,同时系统会自动切割,查看命令只需grep一下shell_cmd即可,美中不足是cronjob不是每天0点执行,所以日志不是按天分割,两天的日志会混在一起

三、直接打到指定文件

bash命令即使记录时间非常久也很小,不需要切割;同时为方便查看,不想bash历史日志和message日志混在一起,所以需要单独打到一个文件中。只需按第二种做法稍稍改变一下即可,同样编辑/etc/profile文件,在最后加入:

    function log2file
    {
export HISTTIMEFORMAT="[%Y-%m-%d %H:%M:%S] [`who am i 2>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'`] "
export PROMPT_COMMAND='\
  if [ -z "$OLD_PWD" ];then
        export OLD_PWD=$(pwd);
  fi;
  if [ ! -z "$LAST_CMD" ] && [ "$(history 1)" != "$LAST_CMD" ]; then
        echo  `whoami`_shell_cmd "[$OLD_PWD]$(history 1)" >>/var/log/bash_history.log;
  fi ;
  export LAST_CMD="$(history 1)";
  export OLD_PWD=$(pwd);'
}    
trap log2file DEBUG

将logger命令改成echo,即可将bash历史记录打到/var/log/bash_history.log

四、三种做法的效果

正常做法,使用syslog,日志输出到/var/log/bash_history.log ,格式:

Feb 20 01:44:07 Centos-Test root: root     pts/2        2016-02-20 01:44 (will-pc.nixops.me) [17983]: ps -ef [0]

第二种方法,通过logger使用syslog,日志输出到/var/log/messages,格式:

Feb 20 01:37:44 Centos-Test root: root_shell_cmd [/etc/rsyslog.d] 1179  [2016-02-20 01:37:44] [will-pc.nixops.me] ps -ef

第三种方法,不用syslog直接打到文件,日志输出到/var/log/bash_history.log,格式:

    root_shell_cmd [/root]   76  [2016-03-27 07:27:41] [10.11.15.41] vim /var/log/messages

参考文章:

https://www.ttlsa.com/linux/history-record-in-message-log/
http://askubuntu.com/questions/93566/how-to-log-all-bash-commands-by-all-users-on-a-server

最新文章

最近回复

  • immortal: 大佬好强!!!
  • myogg: 您好,这个能不能将发...
  • 大青蛙子: 照着大佬的命令行复刻...
  • see: 把虚拟机平台下面其他...
  • see: 感觉是兼容性问题,我...
  • see: 做了。因为inter...
  • see: 遇到一个ipv6问题...
  • pluveto: 这功能很好
  • mgt: 从fail2ban的...
  • see: 设置容器 allo...

分类

归档

统计

  • 文章总数:169篇
  • 分类总数:5个
  • 评论总数:130条
  • 页面总数:173个
  • 本站运行:5200天

其它