日志

Nginx 禁止通过IP直接访问网站

网站备案时需要禁止IP直接访问,否则会存在风险

  • Nginx配置

nginx配置非常简单,只需要添加一个空白的server即可

server{

<pre><code>server_name _;

return 444;
</code></pre>

}

你也可以跳转到你的域名

server {
    server_name _;
    rewrite ^(.*) http://www.yourdomain.com;
}
  • 关于 444 响应状态码

444状态码用于Nginx表示服务器没有任何返回信息,并且会关闭连接.

转载请注明出处:

© http://hejunhao.me

日志

Python正则表达式的使用(re模块)

正则表达式不属于任何语言本身,而是独立的用于处理字符串的强大工具,它有独立的语法和处理引擎,只要你熟悉其语法任何语言下都能使用(部分非常用语法可能在各种语言中的支持不一致)Python处理正则表达式主要用到re模块,本文主要介绍re模块的使用,正则表达式相关语法不作为本文重点

  • 相关语法参考

Python正则表达式常用语法解释

  • 关于re模块

re是 regular expression 的缩写,即正则表达式.

通过re模块使用正则表达式主要有三个过程:

  1. 编译正则表达式得到Pattern对象
  2. 通过Pattern对象匹配文本得到Match对象
  3. 从Match对象中获取匹配信息
  • re.compile(pattern[, flag]):

re.compile的第一个参数指定正则表达式字符串,第二个参数可选,用于指定匹配模式:

re.I(IGNORECASE): 忽略大小写
re.M(MULTILINE): 多行模式
re.S(DOTALL): 点任意匹配模式
re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
re.X(VERBOSE): 详细模式.这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释.

该方法返回一个Pattern对象,实际上它是Pattern类的 Factory Method

  • Match对象

每个pattern匹配成功都会返回一个match对象的结果,通过它我们可以获取一次成功匹配的诸多信息

其常用的方法如下:

group([group1, …]): 返回匹配的一组或多组结果,没有则为None,其中参数group1…可以使用别名也可以使用编号,代表第n组结果,当编号为0时代表整个匹配的子串,若参数为多个则以元组形式返回,若不给参数则视为group(0)

groups([default]):返回所有组的匹配结果的元组,相当于group(1,2,3…),没有匹配到的组以default代替,默认None

groupdict([default]): 返回有别名的组的匹配结果的字典,其中别名为键,匹配子串为值

start([group]): 返回指定组的匹配子串在string中的起始索引,group默认值为0

end([group]): 返回指定组的匹配子串在string中的结束索引(最后一个字符的索引+1),group默认值为0

span([group]): 等价于(start(group), end(group))

#-*- coding:utf-8 -*-
import re
p = re.compile(r'My name is (\w+), I am (?P<age>\d+) years old , I come from (?P<city>\w+).')
m = p.match('My name is Felix, I am 10 years old , I come from Canton.')

print "group(0):", m.group(0)
print "group(1):", m.group(1)
print "groups():", m.groups()
print "groupdict():", m.groupdict()
print "start(1):", m.start(1)
print "end(1):", m.end(1)
print "span(1):", m.span(1)

##输出##
# group(0): My name is Felix, I am 10 years old , I come from Canton.
# group(1): Felix
# groups(): ('Felix', '10', 'Canton')
# groupdict(): {'city': 'Canton', 'age': '10'}
# start(1): 11
# end(1): 16
# span(1): (11, 16)
  • Pattern对象

阅读全文

日志

Python正则表达式常用语法解释

正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串

  • 正则表达式的作用

  1. 给定的字符串是否符合指定正则表达式的过滤逻辑,即匹配(例如Email地址检测,电话号码合法性判断等)
  2. 根据正则表达式从指定字符串中捕获特定的信息(例如从文章中获取所有含有a字母的单词)
  • 正则表达式的特点

  1. 灵活性、逻辑性、功能性非常强大
  2. 以极简的方式控制复杂的字符串
  3. 可读性差,对初学者晦涩难懂
  • 正则表达式语法(包括Python的专用扩展)

正则表达式由普通字符和元字符两大部分组成,而元字符相当于正则表达式的游戏规则,是其灵魂所在.因此,要掌握正则表达式在表达什么,最关键的就是要弄懂它的元字符的作用规则.

一般字符

.(点号)

匹配除了换行符之外的任意字符,在DOTALL模式下可以匹配换行符

例如:a.cd 匹配 abcd
阅读全文

日志

Ubuntu14.04 搭建 LNMP 环境

  • 环境

系统:Ubuntu 14.04.1 LTS

下面所有的安装都通过apt-get的方式,为了防止安装过程报错建议先执行一次更新

sudo apt-get update
  • MySQL安装

sudo apt-get install mysql-server mysql-client

安装期间会出现类似如下的Y/N选择,直接Y 回车即可(下同)

root@li568-33:/# sudo apt-get install mysql-server mysql-client
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
libaio1 libdbd-mysql-perl libdbi-perl libmysqlclient18 libterm-readkey-perl
mysql-client-5.5 mysql-client-core-5.5 mysql-common mysql-server-5.5
mysql-server-core-5.5
Suggested packages:
libclone-perl libmldbm-perl libnet-daemon-perl libplrpc-perl
libsql-statement-perl tinyca mailx
The following NEW packages will be installed:
libaio1 libdbd-mysql-perl libdbi-perl libmysqlclient18 libterm-readkey-perl
mysql-client mysql-client-5.5 mysql-client-core-5.5 mysql-common
mysql-server mysql-server-5.5 mysql-server-core-5.5
0 upgraded, 12 newly installed, 0 to remove and 123 not upgraded.
Need to get 0 B/9,260 kB of archives.
After this operation, 96.5 MB of additional disk space will be used.
Do you want to continue? [Y/n]y

中途会出现新的界面设置MySQL的root用户密码

首先设置root密码:yourpassword
然后重复输入root密码:yourpassword

等安装结束后输入以下命令查看是否成功

mysql --version

正常会显示类似以下的版本信息,则安装完成

mysql  Ver 14.14 Distrib 5.5.43, for debian-linux-gnu (x86_64) using readline 6.3

mysql的配置文件在:/etc/mysql/my.cnf
例如:若要允许远程访问请注释my.cnf 的 bind_address 127.0.0.1

  • Nginx安装

阅读全文

日志

Ubuntu下通过Crontab设置计划任务

  • 简介

cron 是一个在指定时间执行指定任务的系统守护进程.

crontab是一个简单的文本文件,它包含一行行的指令,以及指定每行指令何时执行的时间参数.它通过特定的方式进行编辑,crontab中的每一行命令会在设定的时间由cron在后台执行.每个用户均有其独立的crontab文件,不管用户是否已经登录系统,crontab中的命令都会在规定的时间被执行.如果你的任务需要用到管理员权限(administrative privileges),你可以通过root的crontab创建你的计划任务.

  • 创建计划任务

为当前用户创建一个计划任务

crontab -e

如果你希望任务以管理员权限运行,将其加入到root的crontab下即可

sudo crontab -e

首次创建会要求你先选择默认的文本编辑器,自行决定. 如需更换编辑器可执行以下指令

select-editor

crontab文件类似这样,你可以根据指定的格式编辑添加你的crontab计划任务

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
*/10 * * * * cd /var/www/test && python task.py >> ~/test.log

其中 */10 * * * * cd /var/www/test && python task.py >> ~/test.log 就是一个计划任务的全部配置

一条crontab的配置分为六段,其中前五段属于时间段,用于指定执行的时间,第六段属于命令段,用于指定要执行的命令.除了命令段以外,其他各段不能包含空格,段与段之间允许空格.

每段的意思如下:

分钟 (0-59), 小时 (0-23, 0 = 凌晨), 日 (1-31), 月 (1-12), 星期 (0-6, 0 = 星期日), 命令

多个时间值用逗号隔开,区间用横杠表示(例如 1-5),时间步长控制以斜杠标识,例如上面 */10 的写法是指每隔10分钟的意思,其等价于 0,10,20,30,40,50  (* 和 */1 等价).上面的crontab的意思是指每隔10分钟执行一次命令

“cd /var/www/test && python task.py >> ~/test.log”

终极例子

阅读全文

日志

MAMP PRO 安装PHP扩展 以Memcache为例

1.编译memcache模块需要php的源码,根据php版本去官网下载php的源码,我的是php5.3.29

2.生成zend_config.h备用

cd php5.3.29

./configure

3.安装autoconf,已安装可以无视

curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.68.tar.bz2;

tar -xvf autoconf-2.68.tar.bz2

cd autoconf-2.68

./configure &amp;&amp; make

sudo make install

4.下载编译安装

curl -O http://pecl.php.net/get/memcache-2.2.4.tgz;

tar xf memcache-2.2.4.tgz;

cd memcache-2.2.4;

mkdir /Applications/MAMP/bin/php/php5.3.29/include/

# /Volumes/SOFT/php-5.3.29 是 php 的目录,根据实际自己改
ln -s /Volumes/SOFT/php-5.3.29 /Applications/MAMP/bin/php/php5.3.29/include/php

#建议 pwd 一下看看当前目录是不是memcache-2.2.4下,下面两行命令都必须要在这个目录下执行
/Applications/MAMP/bin/php/php5.3.29/bin/phpize;

./configure --with-php-config=/Applications/MAMP/bin/php/php5.3.29/bin/php-config

make

sudo make install

5.修改php.ini的配置

(!!!!不是到MAMP/bin/php/php.3.29/conf/php.ini下修改,这样是不会生效的,曾经被坑过!)
点 mamp 菜单,file->edit template -> php -> php 5.3.29 php.ini ,增加:

extension = memcache.so

MAMP会提示重启服务,yes就好了

安装结束

在页面输出一下PHPinfo(),command+f 搜索Memcache是否已经enable即可.

转载请注明出处:

© http://hejunhao.me

日志

PHP 基于 MySQL数据 导出 EXCEL文件

操作Excel可以使用第三方开源库,例如强大的:PHPEXCEL.

这里主要采用的是非第三方类库依赖,而是基于PHP5原生支持的fputcsv实现,基本可以满足日常需求.

<?php
// 输出Excel文件头 
header('Content-Type: application/vnd.ms-excel;charset=gbk');
header('Content-Disposition: attachment;filename="文件名.csv"');
header('Cache-Control: max-age=0');

// 从数据库中获取数据 
$sql = 'select * from `table` where ……';
$stmt = @mysql->query($sql);

// PHP文件句柄,php://output 表示直接输出到浏览器 
$fp = fopen('php://output', 'a');

// 输出Excel列头信息 
$head = array('姓名', '性别', '年龄', 'Email', '电话', '……');
foreach ($head as $i => $v) {
    // CSV的Excel支持GBK编码,一定要转换,否则乱码 
    $head[$i] = iconv('utf-8', 'gbk', $v);
}

// 写入列头 
fputcsv($fp, $head);

// 计数器 
$cnt = 0;
// 每隔$limit行,刷新一下输出buffer,节约资源 
$limit = 100000;

// 逐行取出数据,节约内存 
while ($row = $stmt->fetch(FETCH_NUM)) {

    $cnt ++;
    if ($limit == $cnt) { //刷新一下输出buffer,防止由于数据过多造成问题 
        ob_flush();
        flush();
        $cnt = 0;
    }

    foreach ($row as $i => $v) {
        $row[$i] = iconv('utf-8', 'gbk', $v);
    }
    fputcsv($fp, $row);
}
日志

MySQL修改用户密码和重命名用户名

  • 修改用户密码

mysql修改用户密码通过 SET PASSWORD 语句实现

# 修改当前用户的密码

SET PASSWORD = PASSWORD('密码文本') | OLD_PASSWORD('密码文本') | '密码哈希'

注意:OLD_PASSWORD方法使用 mysql 4.1版本以前 的方式对密码进行哈希加密处理,高版本mysql可以通过此方式兼容旧版的用户密码

# 修改用户 alice 的密码为 123456(必须具备 `mysql` 数据库的 UPDATE 权限),host不指定时默认为 '%'

SET PASSWORD FOR 'alice'@'localhost' =  PASSWORD('123456');
  • 重命名用户

mysql修改用户名通过 RENAME USER 语句实现

# 将 alice 用户名修改为 bob,host不指定时默认为 '%'

# 必须要具备`mysql` 数据库的 UPDATE 权限或 CREATE USER 权限,当系统变量 read_only 为 enabled 时还需具备SUPER权限

RENAME USER 'alice'@'localhost' TO 'bob'@'localhost';
转载请注明出处:

© http://hejunhao.me

日志

MySQL添加用户、授权和访问控制

  • 有哪些方式?

你可以通过两种方式创建MySQL用户:

  1. 通过账户管理语句,例如GRANT、CREATE USER等.
  2. 直接用INSERT、UPDATE、DELETE等语句操作MySQL的授权表(mysql.user、mysql.host、mysql.db、mysql.tables_priv、mysql.columns_priv)

显然方式1比方式2更简洁和有助于减少错误

另外你也可以通过GUI工具(如:MySQL WorkBench)或第三方程序(如:phpmyadmin)

  • 通过账户管理语句实现

a) 通过root用户(或具备CREATE USER 权限的用户)连接mysql

mysql -u root -p 你的用户密码

b) CREATE USER 语句用法

# 创建一个名为 alice 密码为 alicepass 的用户,该用户只能从 localhost 连接

CREATE USER 'alice'@'localhost' IDENTIFIED BY 'alicepass';
# 创建一个名为 bob 密码为 bobpass 的用户,允许该用户从任意host连接

CREATE USER 'bob'@'%' IDENTIFIED BY 'bobpass';
# 创建一个名为 chris 密码为 chrispass 的用户,该用户允许从任何 example.com 域名下的host来连接

CREATE USER 'chris'@'%.example.com' IDENTIFIED BY 'chrispass';

c) GRANT 语句用法

# 给 alice 用户分配所有权限,必须要从 localhost 连接

GRANT ALL PRIVILEGES ON *.* TO 'alice'@'localhost' WITH GRANT OPTION;
# 给  bob 用户分配所有数据库的 RELOAD、PROCESS 权限,并且可以把这些权限授权给其他用户(WITH GRANT OPTION的作用)

GRANT RELOAD,PROCESS ON *.* TO 'bob'@'%' WITH GRANT OPTION;
# 给 chris 用户分配 customer 数据库的 SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 权限,必须从任何 example.com 域名下的host来连接

GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON customer.* TO 'chris'@'%.example.com';

d) REVOKE 语句用法

# 撤销 david 用户所有数据库的所有权限

REVOKE ALL PRIVILEGES ON *.* FROM 'david'@'%';

e) DROP USER 语句用法

# 删除 alice 用户,不再允许该用户从localhost连接,不指定host时默认为 '%' ,DROP USER不会自动关闭任何已经打开的用户SESSION,一旦SESSION被关闭则该用户即被移除

DROP USER 'alice'@'localhost';
转载请注明出处:

© http://hejunhao.me

日志

Nginx与Apache的区别

可以举一个简单的例子来说明Apache的工作流程,我们平时去餐厅吃饭.餐厅的工作模式是一个服务员全程服务客户,流程是这样,服务员在门口等候客人(listen),客人到了就接待安排的餐桌上(accept),等着客户点菜(request uri),去厨房叫师傅下单做菜(磁盘I/O),等待厨房做好(read),然后给客人上菜(send),整个下来服务员(进程)很多地方是阻塞的.这样客人一多(HTTP请求一多),餐厅只能通过叫更多的服务员来服务(fork进程),但是由于餐厅资源是有限的(CPU),一旦服务员太多管理成本很高(CPU上下文切换),这样就进入一个瓶颈.

再来看看Nginx得怎么处理?餐厅门口挂个门铃(注册epoll模型的listen),一旦有客人(HTTP请求)到达,派一个服务员去接待(accept),之后服务员就去忙其他事情了(比如再去接待客人),等这位客人点好餐就叫服务员(数据到了read()),服务员过来拿走菜单到厨房(磁盘I/O),服务员又做其他事情去了,等厨房做好了菜也喊服务员(磁盘I/O结束),服务员再给客人上菜(send()),厨房做好一个菜就给客人上一个,中间服务员可以去干其他事情.整个过程被切分成很多个阶段,每个阶段都有相应的服务模块.我们想想,这样一旦客人多了,餐厅也能招待更多的人.

第 4 页,共 5 页12345