CentOS下设置代理上网各种小技巧

最近有人问CentOS如何设置各种代理上网;下面就为大家带来CentOS设置各种代理上网的方法;有需要的朋友可以看看。   1、网页上网​ 桌面版的Centos的话,网页上网设置代理很简单,在firefox浏览器下 : Edit-->>Prefe...
继续阅读 »
Centosimage.png

最近有人问CentOS如何设置各种代理上网;下面就为大家带来CentOS设置各种代理上网的方法;有需要的朋友可以看看。
 


1、网页上网​


桌面版的Centos的话,网页上网设置代理很简单,在firefox浏览器下 :
Edit-->>Preferences-->>Advanced-->>Network
在Connection下点击Settings,里面的manual proxy configuration里设置IP和PORT即可。
 


2、yum代理设置


编辑文件为:/etc/yum.conf ,在里面添加这一行:
proxy=IP:PORT
这里的IP是你代理服务器的ip,端口也是你代理服务器的服务端口。
 


3、wget代理设置


编辑文件为:/etc/wgetrc , 添加下面两行:
http_proxy = IP:PORT  
ftp_proxy = IP:PORT

 


4、系统环境代理设置


编辑文件为/etc/profile,如果只想给自己的账户设置,则编辑~/.bashrc即可
添加如下三行:
# add proxy for network
export http_proxy=http://child-prc.intel.com:913
export https_proxy=http://child-prc.intel.com:913
export ftp_proxy=$http_proxy
然后source /etc/profile 或者source ~/.bashrc即可 收起阅读 »

Centos下扩展PHP模块Imagick详解

PHP
简介 imagick是一个PHP的扩展,它调用ImageMagick提供的API来进行图片的操作 ImageMagick是一套软件系列,主要用于图片的创建、编辑以及转换等,详细的解释见ImageMagick的官方网站http://www.ima...
继续阅读 »
PHP.png


简介


imagick是一个PHP的扩展,它调用ImageMagick提供的API来进行图片的操作

ImageMagick是一套软件系列,主要用于图片的创建、编辑以及转换等,详细的解释见ImageMagick的官方网站http://www.imagemagick.org/  ,ImageMagick与GD的性能要高很多,如果是在处理大量的图片时更加能体现ImageMagick的性能。
 
通常安装安装php的imagick扩展模块有两种方法,一种是利用pcel安装imagick(适用于php verison 5.4 或者更高),第二种就是手动下载编译安装,下面依次介绍。


一、pcel安装imagick


1、首先安装ImageMagick
# cd /usr/local/src/
# wget ftp://ftp.u-aizu.ac.jp/pub/graphics/image/ImageMagick/imagemagick.org/ImageMagick-6.8.7-0.tar.gz
# tar zxf ImageMagick-6.8.7-0.tar.gz
# cd ImageMagick-6.8.7-0
# ./configure -prefix=/usr/local/imagemagick
# make && make install
官网地址:http://www.imagemagick.org/
 
2、安装imagick
# 首先进入到PHP的bin目录
# cd /usr/local/php5.6.26/bin/
# ./pecl install imagick

................
Build process completed successfully
Installing '/usr/local/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226/imagick.so'
Installing '/usr/local/php5.6.26/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.4.3RC1
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini
产生的imagick.so文件拷贝到/usr/local/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226下
 
在php.ini文件里添加imagick.so,然后重启php加载imagick模块即可,使用/usr/local/php5.6.26/bin/php -m 命令查看模块是否添加成功。


二、编译安装imagick


1、首先安装ImageMagick 同上
 
2、编译安装imagick
# wget http://pecl.php.net/get/imagick-3.1.2.tgz
# tar zxf imagick-3.1.2.tgz
# cd imagick-3.1.2
# /usr/local/php5.3.6/bin/phpize (这个看你php安装路径)
# 注:phpize是一个shell脚本,主要是用来进行编译环境的准备,执行以后会生成一些新的文件,为配置、编译及安装作好准备
# ./configure --with-php-config=/usr/local/php5.3.6/bin/php-config --with-imagick=/usr/local/imagemagick
# make && make install
在php配置文件php.ini中添加:
extension=imagick.so
重启apache或php-fpm就可以了。 收起阅读 »

流量劫持与防范

DNS
摘要 流量劫持现象在国内十分猖獗,6家国内顶级互联网公司呼吁有关运营商严格打击流量劫持问题。流量劫持分为域名劫持和内容篡改两类,通过HTTP DNS产品和内容HTTPS加密可以基本解决这两类问题。   概述 2015年12月15日,今日头条、美团大众点...
继续阅读 »


摘要


流量劫持现象在国内十分猖獗,6家国内顶级互联网公司呼吁有关运营商严格打击流量劫持问题。流量劫持分为域名劫持和内容篡改两类,通过HTTP DNS产品和内容HTTPS加密可以基本解决这两类问题。
 


概述


2015年12月15日,今日头条、美团大众点评网、360、腾讯、微博、小米科技六家公司发表联合声明,共同呼吁有关运营商严格打击流量劫持问题,重视互联网被流量劫持可能导致的严重后果。

联合声明指出,在当前的移动互联网环境下,流量劫持主要分为两种方式:域名劫持和数据劫持,放任流量劫持会导致扰乱市场秩序、损害用户利益以及传播诈骗、色情等低俗甚至严重违法信息的恶果。

而在2015年11月,上海浦东法院也刚刚对中国大陆地区首例流量劫持刑案作出判决,两名被告人被判有期徒刑三年,缓刑三年,扣押在案的作案工具以及没收退缴在案的违法所得。

在此前的很长时间内,流量劫持行为并没有被定义为刑事犯罪,而随着浦东法院的判决、六大互联网公司联合声明的发出,流量劫持正在得到更大范围的关注。如何防范流量劫持正成为各家互联网公司的探讨重点。

就此,记者联系了阿里云资深开发工程师亭林,请他介绍了流量劫持的技术原理以及相应的防范措施,精简分享如下。
 
相对于PC端的网络环境,移动端的网络环境更为复杂,2G、3G、4G、Wi-Fi各有不同,而复杂的网络环境也增加了流量劫持的可能性和复杂程度。
 
首先流量劫持的方式主要分为两种,域名劫持和数据劫持。
 


域名劫持


域名劫持是针对传统DNS解析的常见劫持方式。用户在浏览器输入网址,即发出一个HTTP请求,首先需要进行域名解析,得到业务服务器的IP地址。使用传统DNS解析时,会通过当地网络运营商提供的Local DNS解析得到结果。域名劫持,即是在请求Local DNS解析域名时出现问题,目标域名被恶意地解析到其他IP地址,造成用户无法正常使用服务。
DnsDomain.png

解决域名劫持的一个办法就是绕开Local DNS,通过一个可信的源头来解析域名,解析方式不需要拘泥于DNS协议,也可以通过HTTP的方式。两年前,手机淘宝等APP也曾遇到这一问题,随后在做底层网络优化时,通过使用自己定制的HTTPDNS,一个安全可信的域名解析方案,解决了域名劫持问题。

HTTPDNS技术也准备通过阿里云平台开放给广大开发者使用,当前这款产品正在公测中,将于2016年3月29日提供商业化服务。到时,阿里云上的移动开发者也能自主选择,将需要防劫持的域名进行保护。
 


数据劫持


数据劫持基本针对明文传输的内容发生。用户发起HTTP请求,服务器返回页面内容时,经过中间的运营商网络,页面内容被篡改或加塞内容,强行插入弹窗或者广告。

行业内解决的办法即是对内容进行HTTPS加密,实现密文传输,彻底避免劫持问题。MD5校验同样能起到防止数据劫持的作用,MD5校验是指内容返回前,应用层对返回的数据进行校验,生成校验值;同时,内容接收方接收到内容后,也对内容进行校验,同样生成校验值,将这两个校验值进行比对,倘若一致,则可以判断数据无劫持。但相比HTTPS加密,MD5校验存在一定风险,劫持方技术能力强则有可能在篡改内容后替换校验值,导致接收方判断错误。

使用HTTPS加密,已经成为了互联网行业的大势所趋。今年双11,阿里的淘宝、天猫、聚划算等电商平台也都全面实现了HTTPS加密访问,全站改造投入巨大,但有效防止了资源被劫持,保障了用户的收发信息安全。未来,这一技术将不仅限于电商平台,还将通过阿里云对外输出,赋能更多的中小互联网企业,降低他们的创业成本,在更安全的移动互联网环境中得到发展。


阅读分享:https://yq.aliyun.com/articles/8656?spm=5176.100239.blogcont60033.8.zmhPUY


收起阅读 »

Python最差实践变更

最近在看一些陈年老系统,其中有一些不好的代码习惯遗留下来的坑;加上最近自己也写了一段烂代码导致服务器负载飙升,所以就趁此机会总结下我看到过/写过的自认为不好的Python代码习惯,时刻提醒自己远离这些“最差实践”,避免挖坑。 下面所举的例子中,有一部...
继续阅读 »
python.png
最近在看一些陈年老系统,其中有一些不好的代码习惯遗留下来的坑;加上最近自己也写了一段烂代码导致服务器负载飙升,所以就趁此机会总结下我看到过/写过的自认为不好的Python代码习惯,时刻提醒自己远离这些“最差实践”,避免挖坑。

下面所举的例子中,有一部分会造成性能问题,有一部分会导致隐藏bug,或日后维护、重构困难,还有一部分纯粹是我认为不够pythonic。所以大家自行甄别,取精去糟吧。
 


函数默认参数使用可变对象​


这个例子我想大家应该在各种技术文章中见过许多遍了,也足以证明这是一个大坑。
 
先看错误示范吧:
def use_mutable_default_param(idx=0, ids=[]):
ids.append(idx)
print(idx)
print(ids)

use_mutable_default_param(idx=1)
use_mutable_default_param(idx=2)
输出:
1
[1]
2
[1, 2]
理解这其中的原因,最重要的是有两点:
  1. 函数本身也是一个对象,默认参数绑定于这个函数对象上
  2. append这类方法会直接修改对象,所以下次调用此函数时,其绑定的默认参数已经不再是空list了

 
正确的做法如下:
def donot_use_mutable_default_param(idx=0, ids=None):
if ids is None:
ids = []
ids.append(idx)
print(idx)
print(ids)


try…except不具体指明异常类型


虽然在Python中使用try…except不会带来严重的性能问题,但是不加区分,直接捕获所有类型异常的做法,往往会掩盖掉其他的bug,造成难以追查的bug。

一般的,我觉得应该尽量少的使用try…except,这样可以在开发期尽早的发现问题。即使要使用try…except,也应该尽可能的指定出要捕获的具体异常,并在except语句中将异常信息记入log,或者处理完之后,再直接raise出来。
 


关于dict的冗余代码


我经常能够看到这样的代码:
d = {}
datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]
for k in datas:
if k not in d:
d[k] = 0
d[k] += 1
其实,完全可以使用collections.defaultdict这一数据结构更简单优雅的实现这样的功能:
default_d = defaultdict(lambda: 0)
datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]
for k in datas:
default_d[k] += 1
同样的,这样的代码:
# d is a dict
if 'list' not in d:
d['list'] = []
d['list'].append(x)
完全可以用这样一行代码替代:
# d is a dict
d.setdefault('list', []).append(x)
同样的,下面这两种写法一看就是带有浓浓的C味儿:
# d is a dict
for k in d:
v = d[k]
# do something

# l is a list
for i in len(l):
v = l[i]
# do something
应该用更pythonic的写法:
# d is a dict
for k, v in d.iteritems():
# do something
pass

# l is a list
for i, v in enumerate(l):
# do something
pass
另外,enumerate其实还有个第二参数,表示序号从几开始。如果想要序号从1开始数起,可以使用enumerate(l, 1)。 
 


使用flag变量而不使用for…else语句


同样,这样的代码也很常见:
search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']
found = False
for s in search_list:
if s.startswith('C'):
found = True
# do something when found
print('Found')
break

if not found:
# do something when not found
print('Not found')
其实,用for…else更优雅:
search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']
for s in search_list:
if s.startswith('C'):
# do something when found
print('Found')
break
else:
# do something when not found
print('Not found')

 


过度使用tuple unpacking


在Python中,允许对tuple类型进行unpack操作,如下所示:
# human = ('James', 180, 32)
name,height,age = human
这个特性用起来很爽,比写name=human[0]之类的不知道高到哪里去了。所以,这一特性往往被滥用,一个human在程序的各处通过上面的方式unpack。

然而如果后来需要在human中插入一个表示性别的数据sex,那么对于所有的这种unpack都需要进行修改,即使在有些逻辑中并不会使用到性别。
# human = ('James', 180, 32)
name,height,age, _ = human
# or
# name, height, age, sex = human
有如下几种方式解决这一问题:
  1. 老老实实写name=human[0]这种代码,在需要使用性别信息处加上sex=human[3]
  2. 使用dict来表示human
  3. 使用namedtuple

 
# human = namedtuple('human', ['name', 'height', 'age', 'sex'])
h = human('James', 180, 32, 0)
# then you can use h.name, h.sex and so on everywhere.


到处都是import *


import *是一种懒惰的行为,它不仅会污染当前的命名空间,并且还会使得pyflakes等代码检查工具失效。在后续查看代码或者debug的过程中,往往也很难从一堆import *中找到一个第三方函数的来源。

可以说这种习惯是百害而无一利的。
 


文件操作


文件操作不要使用裸奔的f = open(‘filename’)了,使用with open(‘filename’) as f来让context manager帮你处理异常情况下的关闭文件等乱七八糟的事情多好。
 


野蛮使用class.name判断类型


我曾经遇见过一个bug:为了实现某特定功能,我新写了一个class B(A),在B中重写了A的若干函数。整个实现很简单,但是就是有一部分A的功能无法生效。最后追查到的原因,就是在一些逻辑代码中,硬性的判断了entity.__class__.__name__ == ‘A’。

除非你就是想限定死继承层级中的当前类型(也就是,屏蔽未来可能会出现的子类),否则,不要使用__class__.__name__,而改用isinstance这个内建函数。毕竟,Python把这两个变量的名字都刻意带上那么多下划线,本来就是不太想让你用嘛。
 


循环内部有多层函数调用


循环内部有多层函数调用,有如下两方面的隐患:
  1. Python没有inline函数,所以函数调用本来就会导致一定的开销,尤其是本身逻辑简单的时候,这个开销所占的比例就会挺可观的。
  2. 更严重的是,在之后维护这份代码时,会容易让人忽略掉函数是在循环中被调用的,所以容易在函数内部添加了一些开销较大却不必每次循环都调用的函数,比如time.localtime()。如果是直接一个平铺直叙的循环,我想大部分的程序员都应该知道把time.localtime()写到循环的外面,但是引入多层的函数调用之后,就不一定了哦。

 
所以我建议,在循环内部,如非特别复杂的逻辑,都应该直接写在循环里,不要进行函数调用。如果一定要包装一层函数调用,应该在函数的命名或注释中,提示后续的维护者,这个函数会在循环内部使用。
 


总结


Python是一门非常容易入门的语言,严格的缩进要求和丰富的内置数据类型,使得大部分Python代码都能做到比较好的规范。但是,不严格要求自己,也很容易就写出犯二的代码。上面列出的只是很小的一部分,唯有多读、多写、多想,才能培养敏锐的代码嗅觉,第一时间发现坏味道啊。
 


分享阅读:http://blog.guoyb.com/2016/12/03/bad-py-style/
作者:yubo


收起阅读 »

邮件服务端口介绍

25端口(SMTP):25端口为SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)服务所开放的,是用于发送邮件。  如今绝大多数邮件服务器都使用该协议。当你给别人发送邮件时,你的机器的某个动态端口(大于1024)...
继续阅读 »
mail.png

25端口(SMTP):25端口为SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)服务所开放的,是用于发送邮件。 
如今绝大多数邮件服务器都使用该协议。当你给别人发送邮件时,你的机器的某个动态端口(大于1024)就会与邮件服务器的25号端口建立一个连接,你发送的邮件就会通过这个连接传送到邮件服务器上,保存起来。
 
109端口(POP2):109端口是为POP2(Post Office Protocol Version2,邮局协议2)服务开放的,是用于接收邮件的。

110端口(POP3):110端口是为POP3(Post Office Protocol Version3,邮局协议3)服务开放的,是用于接收邮件的。

143端口(IMAP):143端口是为IMAP(INTERNET MESSAGE ACCESS PROTOCOL)服务开放的,是用于接收邮件的。

目前POP3使用的比POP2广得多,POP2几乎被淘汰,也有某些服务器同时支持POP2和POP3协议。客户端可以使用POP3协议来访问服务端的邮件服务,如今ISP的绝大多数邮件服务器都是使用POP3协议(极少用POP2协议)。在使用邮件客户端程序的时候,会要求输入POP3服务器地址,默认情况下使用的就是110端口。当你用邮件客户端(比如、Thunderbird、foxmail、MS Outlook Express以及各类邮件精灵)登录时,你的机器就会自动用机器的某一个动态端口(大于1024)连接邮件服务器的110端口,服务器就把别人给你发的邮件(之前保存在邮件服务器上),发送到你机器,这样你就可以看到你客户端工具上的收件箱里的新邮件了。

IMAP协议,和POP3协议一样是用来接收邮件的,但是它有它的特别和新颖之处,它是面向用户的,它和POP3协议的主要区别是:用户可以不用把所有的邮件内容全部下载,而是只下载邮件标题和发件人等基本信息,用户可以由标题等基本信息,去决定是否下载邮件全文,用户可以通过客户端的浏览器直接对服务器上的邮件进行操作(比如:打开阅读全文、丢进垃圾箱、永久删除、整理到某文件夹下、归档、)。再简单来说就是:浏览器用的IMAP协议(143端口)来为你接收邮件以及让你很方便的操作服务器上的邮件。邮件客户端用的POP3协议(110端口)来为你接收邮件的全部信息和全文内容保存到你的本地机器成为一个副本,你对邮件客户端上的副本邮件的任何操作都是在副本上,不干涉邮件服务器上为你保存的邮件原本。

上面介绍的SMTP协议、POP2协议、POP3协议、IMAP协议都是不安全的协议。因考虑到网络安全的因素,下面给你介绍基于SSL(Secure Sockets Layer 安全套接层)协议的安全的邮件收发协议。你的邮件在传输过程中可能被网络黑客截取邮件内容,如果你的邮件机密性非常强,不想被收件人以外的任何人和任何黑客截取,或者是涉及国家机密安全的,等等。那么你的邮件就不该使用上述的三种协议进行收发。

若你采用SMTP协议发邮件,那么你发出的邮件从你的机器传到服务器的过程中,可能被黑客截取从而泄露。若你采用POP2或者POP3协议收取邮件,那么你的邮件从服务器传至你当前机器的过程可能被黑客截取从而泄露。

465端口(SMTPS):465端口是为SMTPS(SMTP-over-SSL)协议服务开放的,这是SMTP协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。SMTPS和SMTP协议一样,也是用来发送邮件的,只是更安全些,防止邮件被黑客截取泄露,还可实现邮件发送者抗抵赖功能。防止发送者发送之后删除已发邮件,拒不承认发送过这样一份邮件。

995端口(POP3S):995端口是为POP3S(POP3-over-SSL)协议服务开放的,这是POP3协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。POP3S和POP3协议一样,也是用来接收邮件的,只是更安全些,防止邮件被黑客截取泄露,还可实现邮件接收方抗抵赖功能。防止收件者收件之后删除已收邮件,拒不承认收到过这样一封邮件。

993端口(IMAPS):993端口是为IMAPS(IMAP-over-SSL)协议服务开放的,这是IMAP协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。IMAPS和IMAP协议一样,也是用来接收邮件的,只是更安全些,防止邮件被黑客截取泄露,还可实现邮件接收方抗抵赖功能。防止收件者收件之后删除已收邮件,拒不承认收到过这样一封邮件。 收起阅读 »

亲身经历告诉你应该去哪买域名!

前言 前方私货预警!!由于域名购买都是个人经验,以下内容都是主观体验。想看统计数据的请绕行。   看到那么多人推荐GoDaddy,作为过来人实在是看不下去。 首先说说自己的经历,本人不是专职炒域名的,但是平时喜欢做些小东西,码农本性啊。买域名快10年了,...
继续阅读 »


前言


前方私货预警!!由于域名购买都是个人经验,以下内容都是主观体验。想看统计数据的请绕行。
 
看到那么多人推荐GoDaddy,作为过来人实在是看不下去。

首先说说自己的经历,本人不是专职炒域名的,但是平时喜欢做些小东西,码农本性啊。买域名快10年了,前后也有十几个,其中有一些用到现在,大部分1年以后就没再续。注册商前前后后换过好几家,海外的那几家大的基本上都用过。在这里逐一点评一下。许多时候价格当然重要,但是买东西真的不能只看价格。
 


先说GoDaddy


这个公司的规模够大,毕竟起步早,推广也很不遗余力。但是老实说他们不管是从节操上还是能力上都不太跟得上时代了。黑点实在太多,一条一条写:
 
  1. 最近几年出过好几次DNS被黑的情况,要知道域名注册商的DNS服务器被黑可不是小事情。几千万的网站随时解析不了,但就是这样GoDaddy还是被黑了不止一次。可见内部管理已经僵化,反应不过来了。找则新闻大家练练英语:GoDaddy Hacked, Millions of Sites Down 。
  2. GoDaddy前几年偷域名的事情搞得沸沸扬扬。许多人在GoDaddy上搜好的域名第二天上去买了就发现被GoDaddy给抢注了,到了二级市场价格直接翻上成百上千倍。
  3. 这个公司的定价策略不是很透明。比如有一次看到.com域名2.99刀的,点进去一看原来是要签两年合约的第一年才2.99刀,第二年就要回到14.99.算下来两年也没比namecheap便宜多少。倒不是说真的稀罕这点钱,有的时候就是不喜欢绕着弯儿来骗你的感觉。
  4. 本身的销售团队KPI考核压力太大,连他们的客服都是不遗余力地想卖你东西。有什么问题打电话过去问题还没解决先问你要不要续费,哭笑不得。
  5. DNS更新速度很慢。至少前几年要好几个小时才生效。几年没用了不知道现在有没有好点了。
  6. 他们支持SOPA。对于我来说这是无法接受的互联网公司立场。当然这只是这是我的个人立场,不展开。

但就是这样的一个奇葩公司,不知道为什么在国内有那么多人追捧。我在刚刚开始要买域名的时候也是在某个论坛看到了类似的帖子一边倒地推荐GoDaddy,结果是好多年的窝火。今天愤怒地写出来,就是希望大家不要重蹈覆辙。
 


name.com


在被GoDaddy虐了好几年以后,经朋友推荐了http://name.com,只用了一次就全转过去了。你要说他们有什么特别的,其实真的没什么。就是买东西 -> 付钱 -> 开用。 老实说我们消费者其实真的很容易伺候,只要 许诺多少=给多少 的大家基本上就跪了。价格上来说,新注册的会比GoDaddy贵一些,10刀左右,但人家续费也是同一个价,不会一不小心被高价续费,那叫一个心疼。name.com的问题是他们的域名服务器更新速度跟GoDaddy差不多,改个DNS都要好几个小时。
 
但这几年name.com做了几件让我小小不爽的事情:
  1. 大部分域名都提价了,比如.com从$9.99到了$10.99。
  2. 在别人都开始提供免费ssl的时候,他们居然连自己的主站都不用ssl(印象中是今年8月才开始用)。这让我觉得有点不放心。

于是我又问了一圈朋友,终于找到了namecheap。
 


namecheap


真是后知后觉,居然直到去年底才发现这个神器。各方面都不错,是我现在的主注册商,强烈推荐。namecheap的价格不算最便宜的,但是各方面做得真的真的都很好,包括但不限于:速度,控制台,客服响应,稳定性,免费的ssl和whois privacy等等。而且碰到了域名转出和退款什么的都完全不拖泥带水,可以说性价比非常高。
 


enom


enom在国内可能知名度不是很高,但其实是很老牌的域名注册商,namecheap直到最近之前还只是个enom的分销商(就是说他们直到最近才成为ICANN的正式域名注册商)。Google App提供的域名管理后台就是GoDaddy和enom二选一,换句话说Google也是enom的分销商之一。(话说真是怀念几年前的Google App,每个在Google上注册的域名都会送Gmail、Google Calendar等神器,这么多东西一年才10刀实在是超值,想想现在每个月至少要5刀,后悔没多弄几个哎)。
 

enom现在的问题是他们企业路线对我们不友好。这个公司逆互联网的趋势而行,这几年极其注重分销市场,而懒得搭理最终消费者市场(怀疑公司是不是被三哥把持了)。搞到现在他们的零售价格比起name.com和namecheap都要更高一些。而客服也比较不上心。总的来说属于没有太大缺点但是也没什么吸引力的,鸡肋化了。
 


1&1



最后我想专门提一下1&1。如果说GoDaddy是个奇葩的话,这个公司真是奇葩中的战斗机。首先他们家的价格真的是很便宜,便宜到你会有“卧槽有没有搞错”的想法。但是千万不要上当,尤其是绑定信用卡。我再强调一遍,千!万!不!要!上!当!随便在网上搜一把就能看到无数人的血泪史,域名无法转出,域名转出以后信用卡继续扣钱,客服永远没人听电话,客服听不懂英语,要知道这可是美国公司啊亲!
 


购买域名总结


此外,以下为周围朋友闲聊时的总结,我没有真的用过,大家参考一下:

- 很不错的:Gandi,NameSilo,还有最近的uniregistry.com
- 值得一试:IWantMyName, DynaDot
- 很差:http://hover.com据说跟1&1差不多,居然价格还不便宜。另外,大部分的和主机套餐绑定的域名都要慎重考虑,比如Bluehost / Dreamhost等等,他们的问题就是合同很复杂,域名单独续费转出都很麻烦。
 
除了域名注册商以外,还有几个关于站长的问题在这个帖子里也有提及,一起聊一下:
 


SSL


免费的SSL如果放在前几年会很有吸引力,但最近几年门槛越来越低,ssl也不是一个稀罕东西了。随便说几个平民的ssl解决方案:
  1. startssl直接免费 StartSSL™ Certificates & Public Key Infrastructure
  2. cloudflare的免费版自带ssl Home | CloudFlare
  3. @Rio 提到的Comodo确实不错,但是本来也不值几个钱。去Cheap SSL Certificates. Buy or Renew Cheapest SSL at $4.80 也就是4块8美刀一年。

 


Whois Privacy


关于Whois Privacy不是说有免费的提供就一定要用,主要的顾虑是这个可能会影响搜索引擎优化(SEO)。有很多的讨论比如:SEO Question : Do WhoIs Privacy Services Harm SEO?
 
结论都是是出于SEO的目的尽量还是不要隐藏自己的信息。其实这从谷歌的角度也好理解,你从事正当生意那是巴不得全世界都知道你的电话,有什么好怕的?从我个人角度来看我用实名注册了那么多域名都没有因为这个被骚扰过。说到底你的邮件和电话没你想象的那么重要。

当然我知道有人会问,我有证据吗?这个还真没有。可是SEO的事情谁说的准?能做的也就只有可悲的自我审查了。我把这个顾虑留在这儿,大家可以自行判断。
 


DNS记录管理


哪怕是namecheap和name.com,他们的管理界面以2014年的眼光来看都不太好使,DNS刷新速度也不是很理想。我的做法一般是国外域名就直接把name server(域名服务器)转到Home | CloudFlare,国内的转到DNSPod-免费智能DNS解析服务商。速度快,界面好,免费。
 


说了半天,那到底怎么样才能省钱?


好。。好。。别急。。让我喝口水。在离题万里以后回到楼主的问题。现在假设各位看官现在已经被我说服,要买namecheap的.com域名,去了官网一看10.69,算上icann的注册费0.18总共不到11刀,合70人民币左右。
 
土豪当然不在乎,但是相信对于大部分人尤其是学生党来说还是能省则省。于是在这里我又要推荐另一个最近在reddit上很火的神器:Domain Price Comparison (domcomp域名价格网)
 
首先他们在主页上有最新的优惠码,而且更新的很勤快。妈妈再也不用担心每次买域名到处瞎jb搜优惠码了。
domain.jpg


比如现在是2014年10月17号,这个优惠码就是到10月31号之前都可以用,已经比直接注册省了一刀还多了。请大家自行忽略1&1,人生苦短,life is too short to deal with 1&1。(话说GoDaddy居然只要1.49刀才10块人民币 ,把淘宝都秒了有木有。。。。搞得我都有点心动)

当然优惠码还不是最重要的,关键是这个网站还提供返利,可以折上再折,加入方法很简单,点击右上角的affiliate。就是这个:
affiliate.jpg

注册很简洁,填一下邮箱就能进去了(不知道为什么想到了国内那些注册。。。邮箱认证。。手机绑定。。。)
sign.jpg

登陆以后会进到dashboard,也就是控制台。你会看到有一个链接在中间是绿色的,这个就是你的返利链接
program.jpg

下面(请注意这一步很重要),点一下你的返利链接,回到了domcomp.com的主页。是不是看上去什么都没变? 其实不然,你的返利码已经在cookie里面了。接下来就直接点namecheap的价格链接去namecheap注册账号+买域名吧!
 
这个网站反应很快,一般来说买了以后几个小时就会收到邮件确认交易。我现在已经有4个域名通过他们买的(三个.com和一个.io),总共花了八十几刀(io域名真tmd贵)里面有将近20刀的返利。
referral.jpg

仔细算了一下,.com的总共花了40人民币不到,买了namecheap + ssl + whois privacy。而淘宝最便宜的也要60多。这么说来淘宝利润也不错,无本买卖做一单25块钱。
 
最后,买的时候有几点要注意:
  1. 记得每次都要注册新账号,我也不知道为什么,但是namecheap貌似只对新注册账号有返利。
  2. 每次买之前,都最好确认一下返利码在cookie里面,我的做法就是登陆一下专门点一下返利链接,然后再点namecheap。这个时候刷新返利控制台,看看点击数(clicks)有没有增加。比如我刚刚点了一下以后,我的控制台里就从11变成12,也就是说我这个点击是有效的返利点击。

clicks.jpg

利益相关:domcomp.com的链接是我自己的返利链接,也就是说你通过他们买域名的话,除了你实惠以外我也有钱收。


作者:范进
链接:https://www.zhihu.com/question/19551906/answer/31986656
来源:知乎


收起阅读 »

将在2017年受热捧的编程语言「转」

摘要 想知道全球最受欢迎的编程语言是什么吗?它们的判断标准又是怎样的呢? 我们都知道,C++,MATLAB,Java 一直都受到技术学院的青睐,大多数毕业生都热衷于学习这些语言。但它们是否是业界所需要的呢?抱着这个疑问,我们访问了几个可信度较高...
继续阅读 »
2017lang.jpg


摘要


想知道全球最受欢迎的编程语言是什么吗?它们的判断标准又是怎样的呢?

我们都知道,C++,MATLAB,Java 一直都受到技术学院的青睐,大多数毕业生都热衷于学习这些语言。但它们是否是业界所需要的呢?抱着这个疑问,我们访问了几个可信度较高的语言索引网站,同时还深入到 Indeed 和 Glassdoor 等全球门户网站,试图收集数据,以总结出全球最受欢迎的语言是哪些,以及行业内最需要的语言是什么。

注:对编程语言进行受欢迎度评选,并不是为了证明哪项语言好,哪项语言不好, 而是希望能通过这一类分析,找出用户最喜欢以及业界最需要的语言。 
 


TIOBE Index


TIOBE 编程社区索引由荷兰 Eindhoven 的 TIOBE 公司创立和维护。TIOBE 代表着“真诚的重要性”,该索引将每项语言作为关键字,按照搜索引擎的查询数量对语言进行排名。因为 TIOBE 只索引图灵完全的语言,因此 SQL 和 HTML 没有考虑在内。2016年11月的排名结果显示,Java 依然是最受大家欢迎的语言,C 和 C++ 排名紧随其后。出人意料的是,Visual Basic 和 Python 排名有大幅上升,并排在了 Javascript 之前,另外,汇编语言也挤入前十:
index.jpg


PYPL


PYPL(编程语言流行指数)依据 Google 上关于语言教程的搜索频率进行统计。从全球搜索引擎流行度来看,Java 依然是大赢家;Python 较之前五年排名提升 6.8%,而 PHP 暴跌5.0%。
PYPL.jpg

Constantin Brancusi 大学的 Adrian Runceanu 教授在 C++,Java,Oracle 方面有16+年的研究经验。关于 C++ 为什么能在跻身编程语言的前十,他是这么说的:

“我认为 C / C ++ 为大家提供了一个很好的使用机制,我们可以用这项语言创建可移植的应用程序,并且,C/C++ 易于学习,很受学生欢迎。其他语言,如,Javascript,Java,Python 则更适合于 Web 应用程序的开发。我相信 C/C++ 在未来几年依然具有支配性。”


StackOverflow


Stack Overflow 是一个问答平台。它有超过400万的用户,问答了1000多万个问题。根据问题情况,Javascript 的使用者比其他语言的都要多。另外,与 Node 和 Angular 相比,PHP 排名有所下滑。
stackoverflow.jpg


GitHub


在2016年9月年度会议之前,Github 在此分享了其统计报告。

在过去的12个月里,Github 的活跃用户数量超过580万,活跃存储库数量超过1940万。随后它在平台上公布了热门语言排行表。我相信看过这个列表的人都会知道 Javascript 占据了榜首,当然这都没什么好惊讶的,值得惊讶的是它赶超竞争对手的程度之大......
github.jpg

 


HackerEarth


HackerEarth 每月都会为用户提供大量的编码挑战和应聘机会。该公司支持30多种编程语言,用户可随心选择。HackerEarth 内有100多万名程序员,来看看他们最喜欢使用的是什么:
HackerEarth.jpg


Indeed


Indeed 是美国最高流量的工作网站之一,可在50多个国家使用,支持28种语言。按照使用量排名,Java 排在第一位,Javascript,PHP 和 C 以一万多的差距尾随其后。令人惊喜的是,R 语言也出现了竞争的势头。
indeed.jpg

Deepak Garg 教授(数据挖掘以及IEEE计算机协会印度理事会主席的专家)对此的看法是:“计算行业许多工具和应用程序的基本组成都存在着弥合差距,这导致了语言复杂度的演变,使得语言级别比以前更高,这有助于程序员更多地关注逻辑和应用程序,而不仅仅是在实现标准数据类型和构造的复杂结构和语法。


Glassdoor


这个网站的成立使员工可以对组织进行评价。Glassdoor 列出了开发者的工作事项。如果按开发人员的类别排名,该公司最需要的是 Java 开发人员,其次是 Javascript。当然,R 和 C++ 也比较受欢迎,Python 和 Perl 的需求也有了上升。
Glassdoor.jpg


2017年学习的语言


看这趋势,Java 和 Javascript 依然会是 Web 开发行业最受欢迎的语言,Google 的 Go 也乘胜追击,Ruby 还是比较受初创公司的欢迎。根据数据分析,Mozilla 的 RUST 和 Facebook 的 HACK 在2017年下半年也能挤入排名前列。

2017年排名有望上升的语言:
R——如今,世界对统计数据和数据分析的需求越来越大,如果你发现你的工作内容越来越与R挂钩,那么,R成为2017年最受追捧的语言并不是不可能。

MATLA——一旦成为数学家和科学家的核心语言,MATLAB 在分析和统计的领域发挥的作用会越来越大,会有更多的开发人员将回到 MATLAB,因为数学分析的复杂性正在增加。

SQL——随着越来越多的人获得板载技术,数据库的使用一直在呈指数增长。SQL 可谓是为数据库忠实粉量身定做的。

Arduino——这并不是一项新语言,它由 C 和 C++组合而成,随着越来越多的嵌入式芯片等待被编码,Arduino 将有望成为2017年使用的新技能。

Swift——苹果公司面对开发人员的抱怨,决定用 Swift 取代 Objective-C,其编码速度还是十分可观的,目测 Swift 的开发市场会不断扩大。

当然,以上只是我做出的大胆猜测。2017年到底会掀起怎样的编程语言风呢?我们还是拭目以待吧!


译文地址:https://www.oschina.net/news/79650/2017-top-programming-languages
原文地址:http://blog.hackerearth.com/2016/11/top-programming-language-2017.html


收起阅读 »

Elasticsearch 2.2.0节点类型介绍

摘要 在Elasticsearch中节点可以分为主(master)节点,数据(data)节点,客户端节点和部落节点,每种类型的节点有不同的使用方法,对于一个大的集群中,合理的配置这些属性,对集群的健壮性和性能有很大的帮助。   节点类型 当我...
继续阅读 »
elasticsearch.png


摘要


在Elasticsearch中节点可以分为主(master)节点,数据(data)节点,客户端节点和部落节点,每种类型的节点有不同的使用方法,对于一个大的集群中,合理的配置这些属性,对集群的健壮性和性能有很大的帮助。
 


节点类型


当我们启动Elasticsearch的实例,就会启动至少一个节点。相同集群名的多个节点的连接就组成了一个集群,在默认情况下,集群中的每个节点都可以处理http请求和集群节点间的数据传输,集群中所有的节点都知道集群中其他所有的节点,可以将客户端请求转发到适当的节点。节点有以下类型:
  • 主(master)节点:在一个节点上当node.master设置为True(默认)的时候,它有资格被选作为主节点,控制整个集群。
  • 数据(data)节点:在一个节点上node.data设置为True(默认)的时候。该节点保存数据和执行数据相关的操作,如增删改查,搜索,和聚合。
  • 客户端节点:当一个节点的node.master和node.data都设置为false的时候,它既不能保持数据也不能成为主节点,该节点可以作为客户端节点,可以响应用户的情况,并把相关操作发送到其他节点。
  • 部落节点: 当一个节点配置tribe.*的时候,它是一个特殊的客户端,它可以连接多个集群,在所有连接的集群上执行搜索和其他操作。

 
默认情况下,节点配置是一个主节点和一个数据节点。这是非常方便的小集群,但随着集群的发展,分离主节点和数据节点将变得很重要。
 
大家知道Elasticsearch的data node除了放数据以外,也可以兼任master和client的角色,多数同学会将这些角色混入到data node。然而对于一个规模较大,用户较多的集群,master和client在一些极端使用情况下可能会有性能瓶颈甚至内存溢出,从而使得共存的data node故障。data node的故障恢复涉及到数据的迁移,对集群资源有一定消耗,容易造成数据写入延迟或者查询减慢。如果将master和client独立出来,一旦出现问题,重启后几乎是瞬间就恢复的,对用户几乎没有任何影响。另外将这些角色独立出来的以后,也将对应的计算资源消耗从data node剥离出来,更容易掌握data node资源消耗与写入量和查询量之间的联系,便于做容量管理和规划。
 


主(Master)节点说明


主节点的主要职责是和集群操作相关的内容,如创建或删除索引,跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点。稳定的主节点对集群的健康是非常重要的。默认情况下任何一个集群中的节点都有可能被选为主节点。索引数据和搜索查询等操作会占用大量的cpu,内存,io资源,为了确保一个集群的稳定,分离主节点和数据节点是一个比较好的选择
 
虽然主节点也可以协调节点,路由搜索和从客户端新增数据到数据节点,但最好不要使用这些专用的主节点。一个重要的原则是,尽可能做尽量少的工作。创建一个独立的主节点只需在配置文件中添加如下内容:
node.master: true 
node.data: false
为了防止数据丢失,配置discovery.zen.minimum_master_nodes设置是至关重要的(默认为1),每个主节点应该知道形成一个集群的最小数量的主资格节点的数量。解释如下:
 
假设我们有一个集群。有3个主资格节点,当网络发生故障的时候,有可能其中一个节点不能和其他节点进行通信了。这个时候,当discovery.zen.minimum_master_nodes设置为1的时候,就会分成两个小的独立集群,当网络好的时候,就会出现数据错误或者丢失数据的情况。当discovery.zen.minimum_master_nodes设置为2的时候,一个网络中有两个主资格节点,可以继续工作,另一部分,由于只有一个主资格节点,则不会形成一个独立的集群,这个时候当网络回复的时候,节点又会从新加入集群。设置这个值的原则是:
(master_eligible_nodes / 2)+ 1
这个参数也可以动态设置:
PUT localhost:9200/_cluster/settings
{
"transient": {
"discovery.zen.minimum_master_nodes": 2
}
}


数据节点说明


数据节点主要是存储索引数据的节点,主要对文档进行增删改查操作,聚合操作等。数据节点对cpu,内存,io要求较高,在优化的时候需要监控数据节点的状态,当资源不够的时候,需要在集群中添加新的节点。数据节点的配置如下:
node.master: false 
node.data: true
数据节点路径设置,每一个主节点和数据节点都需要知道分片,索引,元数据的物理存储位置,path.data默认位为 $ES_HOME/data,可以通过配置文件 elasticsearch.yml进行修改,例如:
path.data:  /data/es/data/
这个设置也可以在命令行上执行,例如:
./bin/elasticsearch --path.data /data/es/data
这个路径最好进行单独配置,这样Elasticsearch的目录和数据的目录就会分开。当删除了Elasticsearch主目录的时候,不会影响到数据。通过rpm安装默认是分开的。
 
数据目录可以被多个节点共享,甚至可以属于不同的集群,为了防止多个节点共享相同的数据路径,可以在配置文件elasticsearch.yml中添加:node.max_local_storage_nodes: 1
 
注意:在相同的数据目录不要运行不同类型的节点(例如:master, data, client)这很容易导致意外的数据丢失。
 


客户端节点说明


当主节点和数据节点配置都设置为false的时候,该节点只能处理路由请求,处理搜索,分发索引操作等,从本质上来说该客户节点表现为智能负载平衡器。独立的客户端节点在一个比较大的集群中是非常有用的,他协调主节点和数据节点,客户端节点加入集群可以得到集群的状态,根据集群的状态可以直接路由请求。

警告:添加太多的客户端节点对集群是一种负担,因为主节点必须等待每一个节点集群状态的更新确认!客户节点的作用不应被夸大 , 数据节点也可以起到类似的作用。配置如下:
node.master: false 
node.data: false


部落节点说明


部落节点可以跨越多个集群,它可以接收每个集群的状态,然后合并成一个全局集群的状态,它可以读写所有节点上的数据,部落节点在elasticsearch.yml中的配置如下:
tribe:
t1:
cluster.name: cluster_one
t2:
cluster.name: cluster_two
T1和T2是任意的名字代表连接到每个集群。上面的示例配置两集群连接,名称分别是T1和T2。默认情况下部落节点通过广播可以做为客户端连接每一个集群。大多数情况下,部落节点可以像单节点一样对集群进行操作。
 
注意:以下操作将和单节点操作不同,
如果两个集群的名称相同,部落节点只会连接其中一个。由于没有主节点,当设置local为true的是,主节点的读操作会被自动的执行,例如:集群统计,集群健康度。主节点级别的写操作将被拒绝,这些应该是在一个集群进行。部落节点可以通过块(block)设置所有的写操作和所有的元数据操作,例如:
tribe:
blocks:
write: true
metadata: true
部落节点可以也可以在选中的索引块中进行配置,例如:
tribe:
blocks:
write.indices: hk*,ldn*
metadata.indices: hk*,ldn*
当多个集群有相同的索引名的时候,默认情况下,部落的节点将选择其中一个。这可以通过tribe.on_conflict setting进行配置,可以设置排除那些索引或者指定固定的部落名称。 收起阅读 »

Python调用Zabbix API实例

#!/usr/bin/python #coding:utf-8 import json import urllib2 from urllib2 import URLError import sys,argparse class zabbix...
继续阅读 »
#!/usr/bin/python 
#coding:utf-8


import json
import urllib2
from urllib2 import URLError
import sys,argparse

class zabbix_api:
def __init__(self):
self.url = 'http://192.168.210.13:81/zabbix/api_jsonrpc.php' #修改URL
self.header = {"Content-Type":"application/json"}
#验证信息
def user_login(self):
data = json.dumps({
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin", #修改用户名
"password": "zabbix" #修改密码
},
"id": 0
})

request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print "\033[041m 用户认证失败,请检查 !\033[0m", e.code
else:
response = json.loads(result.read())
result.close()
#print response['result']
self.authID = response['result']
return self.authID
#主机查询
def host_get(self,hostName=''):
data = json.dumps({
"jsonrpc": "2.0",
"method": "host.get",
"params": {
"output": "extend",
"filter":{
"host":hostName
}
},
"auth": self.user_login(),
"id": 1
})
request = urllib2.Request(self.url,data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
elif hasattr(e, 'code'):
print 'The server could not fulfill the request.'
print 'Error code: ', e.code
else:
response = json.loads(result.read())
#print response
result.close()
print "主机数量: \033[31m%s\033[0m"%(len(response['result']))
for host in response['result']:
status={"0":"OK","1":"Disabled"}
available={"0":"Unknown","1":"available","2":"Unavailable"}
#print host
if len(hostName)==0:
print "HostID : %s\t HostName : %s\t Status :\033[32m%s\033[0m \t Available :\033[31m%s\033[0m"%(host['hostid'],host['name'],status[host['status']],available[host['available']])
else:
print "HostID : %s\t HostName : %s\t Status :\033[32m%s\033[0m \t Available :\033[31m%s\033[0m"%(host['hostid'],host['name'],status[host['status']],available[host['available']])
return host['hostid']
#图形查询
def graph_get(self,hostids,graphname=''):
data = json.dumps({
"jsonrpc": "2.0",
"method": "graph.get",
"params": {
"output": "extend",
"hostids": hostids,
"sortfield": "name"
},
"auth": self.user_login(),
"id":1
})
request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
elif hasattr(e, 'code'):
print 'The server could not fulfill the request.'
print 'Error code: ', e.code
else:
response = json.loads(result.read())
result.close()
print "图形数量: \033[31m%s\033[0m"%(len(response['result']))
for graph in response['result']:
if len(graphname)==0:
print "graphid : %s\t graphname : %s\t width :\033[32m%s\033[0m \t height :\033[31m%s\033[0m"%(graph['graphid'],graph['name'],graph['width'],graph['height'])
else:
print "graphid : %s\t graphname : %s\t width :\033[32m%s\033[0m \t height :\033[31m%s\033[0m"%(graph['graphid'],graph['name'],graph['width'],graph['height'])
return graph['graphid']
#筛选图查询
def screen_get(self,ScreenName=''):
data = json.dumps({
"jsonrpc": "2.0",
"method": "screen.get",
"params": {
"output": "extend",
"selectScreenItems": "extend",
"filter": {
"name": ScreenName
}
},
"auth":self.user_login(),
"id":1
})

request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print 'Error as ', e
else:
response = json.loads(result.read())
result.close()
print "筛选图数量: \033[31m%s\033[0m"%(len(response['result']))
for screen in response['result']:
if len(ScreenName)==0:
print "ScreenID : %s\t ScreenName : %s\t Hsize :\033[32m%s\033[0m \t Vsize :\033[31m%s\033[0m"%(screen['screenid'],screen['name'],screen['hsize'],screen['vsize'])
else:
print "ScreenID : %s\t ScreenName : %s\t Hsize :\033[32m%s\033[0m \t Vsize :\033[31m%s\033[0m"%(screen['screenid'],screen['name'],screen['hsize'],screen['vsize'])
return screen['screenid']
#主机组查询
def hostgroup_get(self, hostgroupName=''):
data = json.dumps({
"jsonrpc":"2.0",
"method":"hostgroup.get",
"params": {
"output": "extend",
"filter": {
"name": hostgroupName
}
},
"auth":self.user_login(),
"id":1
})

request = urllib2.Request(self.url,data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
#print result.read()
response = json.loads(result.read())
result.close()
#print response()
for group in response['result']:
if len(hostgroupName)==0:
print "hostgroup: \033[31m%s\033[0m \tgroupid : %s" %(group['name'],group['groupid'])
else:
print "hostgroup: \033[31m%s\033[0m \tgroupid : %s" %(group['name'],group['groupid'])
self.hostgroupID = group['groupid']
return group['groupid']
#模版查询
def template_get(self,templateName=''):
data = json.dumps({
"jsonrpc": "2.0",
"method": "template.get",
"params": {
"output": "extend",
"filter": {
"name":templateName
}
},
"auth":self.user_login(),
"id":1
})

request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
response = json.loads(result.read())
result.close()
#print response
for template in response['result']:
if len(templateName)==0:
print "template : \033[31m%s\033[0m\t id : %s" % (template['name'], template['templateid'])
else:
self.templateID = response['result'][0]['templateid']
print "Template Name : \033[31m%s\033[0m "%templateName
return response['result'][0]['templateid']
#主机组创建
def hostgroup_create(self,hostgroupName):
if self.hostgroup_get(hostgroupName):
print "hostgroup \033[42m%s\033[0m is exist !"%hostgroupName
sys.exit(1)
data = json.dumps({
"jsonrpc": "2.0",
"method": "hostgroup.create",
"params": {
"name": hostgroupName
},
"auth": self.user_login(),
"id": 1
})
request=urllib2.Request(self.url,data)

for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
response = json.loads(result.read())
result.close()
print "\033[042m 添加主机组:%s\033[0m hostgroupID : %s"%(hostgroupName,response['result']['groupids'])
#筛选图添加
def screen_create(self,ScreenName,hsize,vsize):
if self.screen_get(ScreenName):
print "Screen \033[42m%s\033[0m is exist !"%ScreenName
sys.exit(1)
data = json.dumps({
"jsonrpc": "2.0",
"method": "screen.create",
"params": {
"name": ScreenName,
"hsize": hsize,
"vsize": vsize
},
"auth": self.user_login(),
"id": 1
})
request=urllib2.Request(self.url,data)

for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
response = json.loads(result.read())
result.close()
print "\033[042m 添加筛选图:%s\033[0m ScreenName : %s"%(ScreenName,response['result']['screenids'])
#筛选图图形添加
def screen_item_create(self,screenid,resourceid,x,y):
if self.screen_item_create(resourceid):
print "resource \033[042m%s\033[0m is exist !"%resourceid
sys.exit(1)
screen_list=[]
for i in screenid.split(','):
var = {}
var['screenid'] = self.screen_get(i)
screen_list.append(var)
data = json.dumps({
"jsonrpc": "2.0",
"method": "screenitem.create",
"params": {
"screenid": screen_list,
"resourceid": resourceid,
"x": x,
"y": y
},
"auth": self.user_login(),
"id": 1
})
request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])
try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
response = json.loads(result.read())
result.close()
print "\033[042m 添加筛选图形:%s\033[0m resourceid : %s"%(resourceid,response['result']['resourceids'])
#主机创建
def host_create(self, hostip, hostgroupName, templateName):
if self.host_get(hostip):
print "\033[041m该主机已经添加!\033[0m"
sys.exit(1)

group_list=[]
template_list=[]
for i in hostgroupName.split(','):
var = {}
var['groupid'] = self.hostgroup_get(i)
group_list.append(var)
for i in templateName.split(','):
var={}
var['templateid']=self.template_get(i)
template_list.append(var)

data = json.dumps({
"jsonrpc":"2.0",
"method":"host.create",
"params":{
"host": hostip,
"interfaces": [
{
"type": 1,
"main": 1,
"useip": 1,
"ip": hostip,
"dns": "",
"port": "10050"
}
],
"groups": group_list,
"templates": template_list,
},
"auth": self.user_login(),
"id":1
})
request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
response = json.loads(result.read())
result.close()
print "添加主机 : \033[42m%s\031[0m \tid :\033[31m%s\033[0m" % (hostip, response['result']['hostids'])
#关闭主机
def host_disable(self,hostip):
data=json.dumps({
"jsonrpc": "2.0",
"method": "host.update",
"params": {
"hostid": self.host_get(hostip),
"status": 1
},
"auth": self.user_login(),
"id": 1
})
request = urllib2.Request(self.url,data)
for key in self.header:
request.add_header(key, self.header[key])
try:
result = urllib2.urlopen(request)
except URLError as e:
print "Error as ", e
else:
response = json.loads(result.read())
result.close()
print '----主机现在状态------------'
print self.host_get(hostip)
#删除主机
def host_delete(self,hostid):
hostid_list=[]
#print type(hostid)
for i in hostid.split(','):
var = {}
var['hostid'] = self.host_get(i)
hostid_list.append(var)
data=json.dumps({
"jsonrpc": "2.0",
"method": "host.delete",
"params": hostid_list,
"auth": self.user_login(),
"id": 1
})

request = urllib2.Request(self.url,data)
for key in self.header:
request.add_header(key, self.header[key])

try:
result = urllib2.urlopen(request)
except Exception,e:
print e
else:

result.close()
print "主机 \033[041m %s\033[0m 已经删除 !"%hostid
#删除筛选图
def screen_delete(self,screenid):
screenid_list=[]
for i in screenid.split(','):
var = {}
var['screenid'] = self.screen_get(i)
screenid_list.append(var)
data=json.dumps({
"jsonrpc": "2.0",
"method": "screen.delete",
"params": screenid_list,
"auth": self.user_login(),
"id": 1
})
request = urllib2.Request(self.url, data)
for key in self.header:
request.add_header(key, self.header[key])
try:
result = urllib2.urlopen(request)
except Exception,e:
print e
else:
result.close()
print "筛选图 \033[041m %s\033[0m 已经删除 !"%screenid


if __name__ == "__main__":
zabbix=zabbix_api()
parser=argparse.ArgumentParser(description='zabbix api ',usage='%(prog)s [options]')
parser.add_argument('-H','--host',nargs='?',dest='listhost',default='host',help='查询主机')
parser.add_argument('-Z','--graph',nargs='?',dest='listgraph',default='graph',help='查询图形')
parser.add_argument('-G','--group',nargs='?',dest='listgroup',default='group',help='查询主机组')
parser.add_argument('-T','--template',nargs='?',dest='listtemp',default='template',help='查询模板信息')
parser.add_argument('-S','--screen',nargs='?',dest='listscreen',default='screen',help='查询筛选图')
parser.add_argument('-A','--add-group',nargs=1,dest='addgroup',help='添加主机组')
parser.add_argument('-C','--add-host',dest='addhost',nargs=3,metavar=('192.168.2.1', 'test01,test02', 'Template01,Template02'),help='添加主机,多个主机组或模板使用分号')
parser.add_argument('-B','--create-screenitem',dest='addscreenitem',nargs=4,metavar=('38', '365', '0', '0'),help='添加筛选图图形')
parser.add_argument('-J','--add-screen',nargs=3,dest='addscreen',help='添加筛选图')
parser.add_argument('-d','--disable',dest='disablehost',nargs=1,metavar=('192.168.2.1'),help='禁用主机')
parser.add_argument('-D','--delete',dest='deletehost',nargs='+',metavar=('192.168.2.1'),help='删除主机,多个主机之间用分号')
parser.add_argument('-P','--delete-screen',dest='deletescreen',nargs='+',metavar=('38'),help='删除筛选图,多个筛选图之间用分号')
parser.add_argument('-v','--version', action='version', version='%(prog)s 1.0')
if len(sys.argv)==1:
print parser.print_help()
else:
args=parser.parse_args()

if args.listhost != 'host' :
if args.listhost:
zabbix.host_get(args.listhost)
else:
zabbix.host_get()
if args.listgraph != 'graph':
if args.listgraph:
zabbix.graph_get(args.listgraph)
else:
zabbix.graph_get()
if args.listgroup !='group':
if args.listgroup:
zabbix.hostgroup_get(args.listgroup)
else:
zabbix.hostgroup_get()
if args.listtemp != 'template':
if args.listtemp:
zabbix.template_get(args.listtemp)
else:
zabbix.template_get()
if args.listscreen != 'screen':
if args.listscreen:
zabbix.screen_get(args.listscreen)
else:
zabbix.screen_get()
if args.addgroup:
zabbix.hostgroup_create(args.addgroup[0])
if args.addhost:
zabbix.host_create(args.addhost[0], args.addhost[1], args.addhost[2])
if args.addscreen:
zabbix.screen_create(args.addscreen[0],args.addscreen[1],args.addscreen[2])
if args.addscreenitem:
zabbix.screen_item_create(args.addscreenitem[0],args.addscreenitem[1],args.addscreenitem[2],args.addscreenitem[3])
if args.disablehost:
zabbix.host_disable(args.disablehost)
if args.deletehost:
zabbix.host_delete(args.deletehost[0])
if args.deletescreen:
zabbix.screen_delete(args.deletescreen[0])
收起阅读 »