阿里云ECS全新实例需要配置安全组规则
最近新买了一台阿里云ECS服务器,新装了httpd服务后,从浏览器无法访问页面。
排查过程如下:
- 服务器是可以ssh登陆的,说明网络没问题
- 在服务器本机使用curl http://127.0.0.1/获取首页,输出OK
- 在服务器本机使用curl http://ecs-外网ip/获取首页,输出OK;这两步说明httpd服务正常
- 检查防火墙,iptables服务未运行
那问题应该在ecs上,网上搜了一下,原来ecs实例设置了安全组规则,默认只开放ICMP、ssh和3389端口。需要手动开放业务端口才行。
方法为:
- 在ECS实例列表处,选择要开放端口的ecs,点击右侧的“管理”
- 在“管理”页面选择左侧“本实例安全组”,进入“安全组”页面
- 点击“配置规则”,然后“添加安全组规则”,设置好协议、端口、授权对象(ip范围)等,保存
稍等一会儿规则生效,就可以正常访问业务页面了。
Boost LRU-Cache使用方法简介
? ? 缓存是提高系统运行效率的常用组件,可以将“有效的”业务数据直接返回用户,避免繁琐的计算过程。除了Redis、MemCache等常用缓存系统,应用程序内部也可以根据需要设置一定容量的缓存,减少跨进程调用,提高效率。
? ? LRU是常用的缓存策略,可以将访问最 频繁的数据保存在有限的缓存中,提高缓存命中率。
? ? 在C++中,可以通过map来保存数据键值对,并通过list将最近使用的数据保存在一端,从list的另一端来清除过期数据的方法实现一个缓存系统。
? ? 然而,我们没必要自己再造一个轮子。Boost-1.65.1版本开始引入了lru_cache算法,通过模板的方式可以方便的实例化出各种类型的缓存对象。
? ? 下面简单介绍boost lru_cache的使用方法。
#lru_cache头文件,这是个header-only库,不需要其他模块
#include <string>
#include <iostream>
using namespace std;
#include <boost/compute/detail/lru_cache.hpp>
int main()
{
const int iCacheSize=100;
#初始化时设置缓存容量
boost::compute::detail::lru_cache<string, string> ssCache(iCacheSize);
#插入数据
ssCache.insert("ZhangSan", "Beijing");
ssCache.insert("LiSi", "Shanghai");
#查找并获取数据
string s("ZhangSan");
if(ssCache.contains(s))
{
#注意!get方法返回的是一个boost::optional<string>对象,而不是直接返回存入其中的Value类型的对象!
boost::optional<string> o_Region=ssCache.get(s);
#我们可以通过boost::optional<string>的get()来获取Value对象
string sRegion=o_Region.get();
cout << s << " comes from " << sRegion << endl;
}
return 0;
}
Shell字符串分割与随机访问
? ? Shell经常做的一项工作就是文本处理,通过组合grep、awk、sed等来实现查找、分割、替换、删除等操作。今天说一下对单行字符串的分割处理方法。先看代码:
_uas="Mozilla/5.0 (Linux; Android 5.1.1; Redmi Note 3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/535.19|Mozilla/5.0 (Linux; Android 4.4.4; 2014813) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/535.19|Linux; Android 6.0.1; SM-G9008W) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/535.19|Mozilla/5.0 (Linux; Android 5.0.2; Redmi Note 2) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/535.19" #生成随机索引 _rand_index=$(expr $RANDOM % 4) #设置新的分隔符 OLD_IFS="$IFS" IFS="|" #将UA字符串分割到_arr数组中 _arr=($_uas) IFS="$OLD_IFS" #通过下标访问数组中的元素。 _ua=${_arr[$_rand_index]}
? ? _uas包含以竖线|分隔的4个安卓UA,我想要随机取其中的一个UA来用。这涉及到两点需求:生成一个随机索引,将字符串按照指定的分隔符来分隔。
? ? Shell生成随机数的方法可以如上面代码一样直接取系统环境变量$RANDOM,也可以通过date +%s的方法获取当前的秒数,再和数组长度取模来实现。当然通过系统时间的方法获得的随机数有可能并不很随机,特别是在操作间隔很短的情况下。
? ? 单行字符串分割可以通过awk来实现,然后分别打印各列的值。但是通过设置系统IFS的方法看起来更直接,能够直接通过($string_line)将元素保存在新的数组中,这样就可以以下标的方式来访问。
? ? Shell还是博大精深的,不常用不足以体会其便捷与强大。
python3 PyMySQL模块的安装和使用
我们知道Python3和Python2是不兼容的,版本由2升级到3之后对MySQL数据库的访问也需要使用新的模块。此前的文章中已介绍过MySQLdb在Python2中的用法,今天介绍PyMySQL在Python3中的用法。
- 安装
- 直接通过pip安装:
pip install PyMySQL
- 直接通过pip安装:
- 示例
- 连接数据库
import pymysql try: conn = pymysql.connect(ip, 3306, user, password, db, charset='utf8', cursorclass=pymysql.cursors.DictCursor) except Exception as e: print("Exception throwed when connect to db: " + str(e))- 插入数据
try: with conn.cursor() as cursor: sql = "insert into t_student(id, name) values (%d, %s)" rows=cursor.execute(sql, (s.id, s.name)) conn.commit() if rows == 1: print("Inserted.") else: print("Failed") except Exception as e: print("Exception throwed when insert data: " + str(e))
c++点滴:string非空判断和随机访问的实现细节和使用方法
- 非空判断
- 一般通过是否等于”” 或者empty()函数的返回值来判断是否为空,结果是一致的
- 差别在于:empty()返回的是string内置变量_M_rep()->_M_length的值,不需要其他计算;而与””比较是需要调用compare(const _CharT* __s)函数来判断的,因此在性能方面,empty()更占优
- 随机访问
- 可通过[]或at()来随机访问,都是通过下标直接访问内部buffer,很快。_M_data()[__pos]。
- 差别在于:at()更安全。当下标超出string.size()时,at()抛出异常,而[]则引发断言错误。
分享一段解析HTTP请求消息头的C++代码
Http请求消息说白了就是\r\n和:分割的一串字符,解析消息头部考察的是基本的字符串操作。当然实际应用中可以使用boost::splitl来辅助处理。
请求消息如下:
GET /suggest?word=http://t.&callback=suggest360&encodein=utf-8&encodeout=utf-8&_h=18.js&outfmt=json HTTP/1.1
Host: sug.so.360.cn:8188
Cache-Control: no-cache
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 QIHU 360SE
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Accept: */*
Cookie: vjuids=a8f919aab.156c5a83b9b.0.3db0cfd7; shenhui12=w:1; gn12=w:1; sci12=w:1; UM_distinctid=15c7168d4207f-083dc20ce-4349052c-100200-15c7168d42346; sohutag=8HsmeSc5NSwmcyc5NSwmYjc5MSwmYSc5NywmZjc5NCwmZyc5NCwmbjc5NjwmaSc5NSwmdyc5NCwmaCc5NCwmYyc5NCwmZSc5NCwmbSc5NCwmdCc5NH0; _muid_=1501816572977065; _ga=GA1.2.1163329499.1503043055; beans_mz_userid=62mbb0GPSAy5; debug_test=sohu_third_cookie; lastpopup=2017-8-19; vjlast=1472194952.1505800087.21; IPLOC=CN1100; SUV=1608221725397504
Range: bytes=17276560-19912545
Referer: http://offp.download.icartoons.cn:8188/client_package/v_4125/7825
解析代码如下:
//存储请求行
string cmdLine=""; ?
//存储消息头各字段和值
map<string, string> kvs; ?
size_t pos=0, posk=0, posv=0;
string k="", v="";
char c;
//http保存了上述GET请求
while(pos != http.size()) ?
{
c=http.at(pos);
if(c == ':')
{
//非请求行,且消息头名称未解析
if(!cmdLine.empty() && k.empty()) ?
{
//存储消息头名称
k = http.substr(posk, pos-posk); ?
//跳过冒号和空格
posv = pos+2; ?
}
}
//行尾
else if(c == '\r' || c=='\n') ?
{
//尚未解析到消息头字段名称,且请求行也未解析过
if(k.empty() && cmdLine.empty()) ?
{
//本行应是请求行,保存之
cmdLine = http.substr(posk, pos-posk); ?
}
else
{
//已解析了消息头字段名称,尚未解析字段值
if(!k.empty() && v.empty()) ?
{
//存储字段值
v = http.substr(posv, pos-posv); ?
}
}
posk=pos+1;
}
if(!k.empty() && !v.empty() && !cmdLine.empty())
{
//保存消息头字段名称和值
kvs.insert(make_pair(k,v)); ?
k="";
v="";
}
++pos;
}
需要注意的是:消息头各字段的值中也有可能出现冒号。
pyquery:Python版的jQuery,HTML页面解析好工具
# coding=utf-8
import requests
from pyquery import PyQuery as pq
#set request header
head_req = {
'User-Agent':'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
'Referer':'http://www.baidu.com/'
}
url = 'http://zhixing.bjtu.edu.cn/portal.php'
r = requests.get(url, headers=head_req)
#build pyquery object from response-content
page = pq(r.content)
#get page title
title = page.find('title')
print title.html()
#get page keyword
kw = page.find('meta[name="keywords"]')
print kw.attr('content')
阿里云OSS python sdk使用简介
阿里云OSS可以方便的存储各类数据,配合CDN的使用,能够极大提高数据的访问效率。向OSS存放数据时一般要登陆阿里云,再进入OSS管理控制台,选择bucket上传文件。手动操作步骤还是有点繁琐的。好在阿里为我们提供了api和sdk,能够实现自动化操作。
这里简单介绍一下阿里云OSS-Python-SDK的使用方法。
- 安装:pip install oss2
- 检查:在Python命令行中输入import oss2;oss2.__version__。安装成功则会显示版本号
- 在OSS管理控制台中创建AccessKey
- 进入OSS控制管理台首页,点右上侧的AccessKey按钮,打开AccessKey管理控制台
- 点击提示框中的“开始使用子用户AccessKey”–>设置用户名–>设置权限,仅选择AliyunOSSFullAccess即可–>开始创建用户–>验证手机号后就创建成功了
- 在“访问控制台RAM”页面的“用户管理”中可看到刚才创建的用户,点击用户名
- 在“用户详情”页的下边能看到“用户AccessKey”,默认已生成了一个AccessKey
- 我们可以随时点右侧的“创建AccessKey”来生成新的AccessKey,创建成功会显示AccessKeyID和AccessKeySecret。这两个参数是通过SDK访问OSS必需的。
- SDK的使用,可参考官方手册快速入门,也可以通过官方提供的示例进行测试。下边的代码演示了如何上传一个文档对象到OSS。
# -*- coding: utf-8 -*- import os import shutil import oss2 # 首先初始化AccessKeyId、AccessKeySecret、Endpoint等信息。 # 把诸如“<你的AccessKeyId>”替换成真实的AccessKeyId等。 # # 以上海区域为例,Endpoint可以是: # http://oss-cn-shanghai.aliyuncs.com # https://oss-cn-shanghai.aliyuncs.com # 分别以HTTP、HTTPS协议访问。 access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID', 'LTdsa52Gjv0Nt6') access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET', 'dijw14JxbYeeKdaght3DG4w0k96KQBHu') bucket_name = os.getenv('OSS_TEST_BUCKET', 'my-bucket') endpoint = os.getenv('OSS_TEST_ENDPOINT', 'oss-cn-shanghai.aliyuncs.com') # 确认上面的参数都填写正确了 for param in (access_key_id, access_key_secret, bucket_name, endpoint): assert '<' not in param, '请设置参数:' + param # 创建Bucket对象,所有Object相关的接口都可以通过Bucket对象来进行 bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name) # 上传文件 “本地座右铭.txt” 到OSS,并命名为 “云上座右铭.txt” with open(oss2.to_unicode('本地座右铭.txt'), 'rb') as f: bucket.put_object('云上座右铭.txt', f)
Httpry:简明http抓包工具
tcpdump是流量分析时最常用的抓包工具,功能很强大。抓取http get交互消息的常用命令是:
tcpdump -XvvennSs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854 -w eth0-http.pcap
通常我们会把抓取的http包保存成文件,然后用wireshark打开分析。
有时候,我们不需要对流量观察得特别深入,仅仅是看一下有什么样的流量,不需要存盘分析。
使用tcpdump的话输出内容不直观,比如wget http://www.baidu.com/的输出如下:
15:05:27.837705 00:16:3e:04:af:53 > ee:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 165: (tos 0x0, ttl 64, id 18764, offset 0, flags [DF], proto TCP (6), length 151)
139.129.205.48.53353 > 220.181.112.244.80: Flags [P.], cksum 0xa6e5 (incorrect -> 0xe0b0), seq 2930938556:2930938667, ack 65362085, win 115, length 111
0x0000: 4500 0097 494c 4000 4006 4ab9 8b81 cd30 E…IL@.@.J….0
0x0010: dcb5 70f4 d069 0050 aeb2 92bc 03e5 58a5 ..p..i.P……X.
0x0020: 5018 0073 a6e5 0000 4745 5420 2f20 4854 P..s….GET./.HT
0x0030: 5450 2f31 2e30 0d0a 5573 6572 2d41 6765 TP/1.0..User-Age
0x0040: 6e74 3a20 5767 6574 2f31 2e31 3220 286c nt:.Wget/1.12.(l
0x0050: 696e 7578 2d67 6e75 290d 0a41 6363 6570 inux-gnu)..Accep
0x0060: 743a 202a 2f2a 0d0a 486f 7374 3a20 7777 t:.*/*..Host:.ww
0x0070: 772e 6261 6964 752e 636f 6d0d 0a43 6f6e w.baidu.com..Con
0x0080: 6e65 6374 696f 6e3a 204b 6565 702d 416c nection:.Keep-Al
0x0090: 6976 650d 0a0d 0a ive….
15:05:27.860678 ee:ff:ff:ff:ff:ff > 00:16:3e:04:af:53, ethertype IPv4 (0x0800), length 449: (tos 0x60, ttl 48, id 47418, offset 0, flags [DF], proto TCP (6), length 435)
220.181.112.244.80 > 139.129.205.48.53353: Flags [P.], cksum 0x6a94 (correct), seq 65362085:65362480, ack 2930938667, win 772, length 395
0x0000: 4560 01b3 b93a 4000 3006 e94e dcb5 70f4 E`…:@.0..N..p.
0x0010: 8b81 cd30 0050 d069 03e5 58a5 aeb2 932b …0.P.i..X….+
0x0020: 5018 0304 6a94 0000 4854 5450 2f31 2e31 P…j…HTTP/1.1
0x0030: 2032 3030 204f 4b0d 0a53 6572 7665 723a .200.OK..Server:
0x0040: 2062 6665 2f31 2e30 2e38 2e31 380d 0a44 .bfe/1.0.8.18..D
0x0050: 6174 653a 2054 6875 2c20 3237 204a 756c ate:.Thu,.27.Jul
0x0060: 2032 3031 3720 3037 3a30 353a 3237 2047 .2017.07:05:27.G
0x0070: 4d54 0d0a 436f 6e74 656e 742d 5479 7065 MT..Content-Type
0x0080: 3a20 7465 7874 2f68 746d 6c0d 0a43 6f6e :.text/html..Con
0x0090: 7465 6e74 2d4c 656e 6774 683a 2032 3338 tent-Length:.238
此时,httpry是一个很好的替代工具。使用httpry捕获上述请求,输出如下:
2017-07-27 15:08:50 139.129.205.48 220.181.112.244 > GET www.baidu.com / HTTP/1.0 – –
2017-07-27 15:08:50 220.181.112.244 139.129.205.48 < – – – HTTP/1.1 200 OK
简单明了。
- 安装
- 下载源码,make && make install就ok了
- 这个程序依赖libpcap-devel库,没有的话就yum install -y libpcap-devel
- 使用
- 最简单的:httpry -i eth0
- 支持过滤http请求方法:httpry -i eth0 -m GET
- 支持保存抓包:httpry -i eth0 -o eth0-http.log
- 可以指定packet filter:httpry -i eth0 ‘dst host www.baidu.com’
一个从MongoDB中导出给定日期范围内数据的shell脚本
前几天介绍了使用mongoexport的使用方法,结合date命令的使用,这里给出一个完整的脚本,用来从MongoDB中导出某个日期范围内的数据,数据导出后从MongoDB中进行删除。
#!/bin/sh
#d1, the beginning date, eg:2017-06-28
d1=$1
d1=`date -d $d1 +%F`
?
#transfer d1 to seconds
d2=`date -d $d1 +%s`
#increase d1 by one day
d2=`expr $d2 + 86400`
#transfer d2 from seconds to day
d2=`date -d @$d2 +%F`
#build query json
qj='{"time":{$gte:ISODate("'"$d1"'T00:00:00Z")}, "time":{$lt:ISODate("'"$d2"'T00:00:00Z")}}'
#export
./mongoexport --db testDB --collection testColl?--query="$qj" --fields="userId,userName" --type="csv" --out results"-$d1" --noHeaderLine
#generate js for delete
echo 'var db = connect("testDB");' > delete.js
echo 'db.testColl.remove({"time":{$gte:ISODate("'"$d1"'T00:00:00Z")}, "time":{$lt:ISODate("'"$d2"'T00:00:00Z")}})' >> delete.js
#delete
./mongo delete.js
备注:如果MongoDB使用的不是默认端口27017,上面的脚本里mongoexport和mongo都需要增加–port参数,并且delete.js中的connect方法也需要指定端口,指定方式为:
var db = connect("127.0.0.1:port/testDB");
近期评论