Gowhich

Durban's Blog

看代码,仔细看

1
2
3
4
5
$postDomain = 'http://127.0.0.1:3333';
$postData = array(
'user_name' => 'lala',
'identity_no' => 'lala',
);

第一个示例

1
2
3
4
5
6
7
8
9
10
11
12
13
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $postDomain . '/api/test');
curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLINFO_HEADER_OUT, 1);
curl_setopt($curl, CURLOPT_POST, 1); // enable posting
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postData)); // post images
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // if any redirection after upload
$r = curl_exec($curl);
curl_close($curl);
$r = json_decode($r);
var_dump($r);

第二个示例

1
2
3
4
5
6
7
8
9
10
11
12
13
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $postDomain . '/api/test');
curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLINFO_HEADER_OUT, 1);
curl_setopt($curl, CURLOPT_POST, 1); // enable posting
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData); // post images
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // if any redirection after upload
$r = curl_exec($curl);
curl_close($curl);
$r = json_decode($r);
var_dump($r);

好了,我们来说下区别

第一个示例请求参数默认是按照“multipart/form-data”格式进行编码的。

第二个示例请求参数默认是按照“application/x-www-form-urlencoded”进行编码的。

特别注意:

php的curl进行post请求的时候,只能传递一维数组作为传递的参数,那么如果想要传递多维数组需要怎么处理?有两种方式可以来处理,分别是下面的方式。

1、将多维数组进行http_build_query()进行处理

这种方式也是通过application/x-www-form-urlencoded进行编码的

2、将多维数组转换为json格式的字符串,对字符串进行application/json格式编码,在接收方通过file_get_contents(“php://input”)或者$GLOBALS[‘HTTP_RAW_POST_DATA’]的方式获取传递过来的json格式的字符串,然后将json格式的字符串转换为数组进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $postDomain . '/api/test');
curl_setopt($curl, CURLOPT_USERAGENT, 'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.15');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // stop verifying certificate
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLINFO_HEADER_OUT, 1);
curl_setopt($curl, CURLOPT_POST, 1); // enable posting
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postData));
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Content-Length: ' . strlen(json_encode($postData))));
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // if any redirection after upload
$r = curl_exec($curl);
curl_close($curl);
$r = json_decode($r);
var_dump($r);

首先检查一下条件是否符合

1、右键项目根本找不到Maven
2、右键项目属性(Properties)也找不到Maven

1】第一个文件.project的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>simple_custom_error_pages</name>
<comment></comment>
<projects></projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments></arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

改为如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>simple_custom_error_pages</name>
<comment></comment>
<projects></projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments></arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments></arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

2】第二个文件.classpath的修改

1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

改为如下

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

supervisor启动flask项目中,配置了uwsgi,即通过supervisor启动uwsgi,uwsgi再启动flask项目
这个过程中uwsgi是个坑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<uwsgi>
<chdir>/relativeProjectPath</chdir>
<module>wsgi_handler</module>
<socket>/tmp/walkerfree-uwsgi.sock</socket>
<daemonize>/tmp/uwsgi.walkerfree.log</daemonize>
<master>4</master>
<chmod-socket>666</chmod-socket>
<enable-threads />
<processes>4</processes>
<harakiri>30</harakiri>
<workers>6</workers>
<memory-report />
<vacuum/>
</uwsgi>

这个是我的初始配置文件,如果单独使用uwsgi启动是没有问题的,但是放在supervisor就有问题,会启动很多个uwsgi进程,而且supersior也会报错
我见到的错误如下几种
1】ERROR (spawn error)
2】BACKOFF Exited too quickly (process log may have details)

先给下最终的uwsgi配置方案,如下

1
2
3
4
5
6
7
8
9
10
11
12
<uwsgi>
<chdir>relativeProjectPath</chdir>
<module>wsgi_handler</module>
<socket>/tmp/walkerfree_uwsgi.sock</socket>
<logto>/tmp/walkerfree_uwsgi.log</logto>
<chmod-socket>666</chmod-socket>
<enable-threads />
<processes>1</processes>
<harakiri>30</harakiri>
<memory-report />
<vacuum/>
</uwsgi>

具体有几个坑吧,我试了两种,具体有一下几个方法
第一个:
修改daemonize为logto
第二个:
去掉master【这项可以不用去掉,如果不起作用可以试试】
去掉workers【这项可以不用去掉,如果不起作用可以试试】
修改processes为1

supervisor中项目的配置如下

1
2
3
4
5
6
7
[program:walkerfree]
# http://supervisord.org/configuration.html#program-x-section-example
command=/projectPath/env/bin/uwsgi -x /projectPath/uwsgi.xml
autostart=true
autorestart=true
stdout_logfile=/projectPath/supervisor/out.log
stderr_logfile=/projectPath/supervisor/err.log

GMS谷歌安装器,下载地址:http://m.appchina.com/app/com.huawei.gmsinstaller

点开这个地址可能会首先下载“应用汇”,不过没关系,安装完之后,搜索gms就可以找到GMS安装器。 安装完之后需要翻墙后才能继续操作哦。

顺便科普下GMS

GMS全称为GoogleMobile Service,即谷歌移动服务。GMS是Google开发并推动Android的动力,也是Android系统的灵魂所在

GMS目前提供有Search、Search by Voice、Gmail、Contact Sync、Calendar Sync、Talk、Maps、Street View、YouTube、Android Market(ICS上更改为Play store)服务。

但是国内大多数手机都或多或少的做了增减,部分手机是没有GMS的,需要自己去安装。

以Jessie为例, 编辑/etc/apt/sources.list文件, 在文件最前面添加以下条目(操作前请做好相应备份)

1
2
3
4
5
6
7
8
deb http://mirrors.163.com/debian/ jessie main non-free contrib
deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib
deb http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ jessie-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib
deb-src http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib

或者下载相应版本的sources.list, 覆盖/etc/apt/sources.list即可(操作前请做好相应备份)

转载:http://mirrors.163.com/.help/debian.html

这个11月,Nodejs新版本更新了,欢呼雀跃呀。

记得大概从2014年刚开始接触,到进入新公司后正式使用Nodejs已经有大概会3年了,大概也算是我比较喜欢的语言中的一种。

第一次接触的时候,就基本上只是用来运行js脚本,当时爬取网站的时候,有很多js的调用,需要运行后才有结果,当时自己还只是在用PHP,重写的话有相当的耗时,于是就有了第一次接触,之后断断续续就没有怎么接触了。

第二次接触是在进入奇鸟后,认识了磊哥,于是又开始了Nodejs之旅,这回让我对js有了重新的认识,以往的普通语法认知和视野认知进入到了一个更深的层面。

当时记得做一个逻辑,需要查询数据库,然后需要根据查询的结果做逻辑处理,要是知道,js的特性,那个时候就是一层层的嵌套,后来在使用过程中,了解到了co,async之类的库,就摆脱了一层一层剥洋葱的感觉,也学会了原来,还可以有这样的库能够被使用

比如下面这样一层一层深入

1
2
3
4
5
6
7
8
9
10
11
connection.query(sql, function(data, function(err, callback) {
if (err) {
return callback();
}

if (data) { // 具体的逻辑处理
connection.query(sql, function(data, function(err, callback) {
// 具体的逻辑处理 可能还有其他的需求
});
}
})

下面试用co跟async的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async.waterfall([
function(callback) {
if (accessToken) {
getUidByToken(accessToken, function(err, uid) {
if (err) {
return callback(null, 0);
}
callback(null, uid);
})
} else {
callback(null, 0);
}
},
function(uid, callback) {
var sql = `... where user_id = uid`;
mysql.query({sql: sql}, function(err, row) {
callback(err, row);
})
}
], function(err) {
if (err) {
return next(err);
}
res.json(OKPacket);
});
1
2
3
4
5
6
7
8
9
10
co(function* () {
let _isAdmin = yield Promise.resolve(true);
if (!_isAdmin) {
throw new Error('Admin only.');
}
let sql = ``;
yield mysql.queyr(sql);
})
.then(val => res.json({suceess: true, data: []}))
.catch(e => next(e));

是不是感觉要比一层一层深入要好很多,虽然是这样,但是依然不能达到自己去深入Nodejs这块的学习。

后来又了解到了koajs,感觉自己时刻跟不上时代的进步,仅仅不到一年的时间,各种新的技术如雨后春笋般,一个一个冒出来。

后来又接触到了Reactjs,ReactNative,Webpack,Gulp,Grunt,Pm2等,短短的时间内感觉自己提升了好几个级别。

但是Nodejs中的各种新的语法也在渐渐的完善。

如今我自己写的代码,大部分是使用了Babel进行了编译后去运行,毕竟使用的版本中很多新的语法还不支持。

比如这个,就是目前我使用了8.9.1这个版本后的.babelrc配置文件

1
2
3
4
5
{
"plugins": [
'transform-es2015-modules-commonjs',
]
}

对比下以前的

1
2
3
4
5
6
7
8
9
10
11
12
{
"presets": ["es2015"],
"plugins": [
'transform-async-to-generator',
'transform-strict-mode',
'transform-object-assign',
'transform-class-properties',
'transform-export-extensions',
'transform-runtime',
'transform-decorators-legacy'
]
}

感觉瞬间清爽了许多,应该在开发中,每次写完代码进行编译的速度都快了很多。再过几年import/export被支持的时候,就彻底释放了。

感觉Nodejs这种语言很随意又很严格,随意就是,你可以啥也不管,只能运行就行,可以使用原来的方式。

严格就是,当你对自己严格的时候,你的代码也会严格起来,而且严格的结果就是感觉新的血液不停的在沸腾。

在使用nodejs中的async/await方法的时候,在map,forEach中使用await的时候,eslint总是提示我no-await-in-loop。对于我比较喜欢正规写代码的人讲,忍受不了这种错误提示。最终还是找到了解决办法。

一般什么情况会有这个错误的呢,如下

1
2
3
4
5
6
7
async test() {
const testData = [1, 2, 3];
testData.forEach((v) => {
// 这里就会提示 no-await-in-loop
const res = await getItem(v); // 假设这里的getItem是一个Promise
})
}

解决的办法如下,改成如下方式就可以了,针对forEach也一并改为map。

1
2
3
4
5
6
7
async test() {
const testData = [1, 2, 3];
testData.map(async (v) => {
// 这里就会提示 no-await-in-loop
const res = await getItem(v); // 假设这里的getItem是一个Promise
})
}

我们在测试的时候会遇到一个情况,就是在做上线前的接口测试的时候,想要模拟真实的环境,那么接口的域名地址是少不了的,这个情况下,我们又不想直接调用线上的数据,想通过域名跟IP的映射,调用另外一台机器上的代码【即将要上线的代码】。可以采用php中curl的参数配置来操作,具体如下:

这里的Curl使用的是ixudra/curl

简单的实例代码如下

1
2
3
4
$response = Curl::to($host)
->enableDebug('/usr/local/openresty/nginx/html/api.qeeniao.com/qeeniao/storage/logs/laravel-2017-11-03.log')
->withOption('RESOLVE',['xxx.xxxx.com:443:xxx.xxx.xxx.xxx'])
->withData($params)->get();

其实熟悉curl的话对这个就不陌生了

1
curl --resolve fdh5imgcdn.oz1997.com:443:58.216.109.182

如果不用ixudra/curl的话,可以参照下面的代码使用,效果其实是一样的

1
2
3
4
5
6
7
8
9
10
11
12
$resolve = array(sprintf(
"%s:%d:%s",
$hostname,
$port,
$host_ip
));

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RESOLVE, $resolve);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);

第一步就是:下载zsh源码包

安装的前提是需要安装ncurses,可以看前面的文章[Centos 之 非root情况下ncurses安装问题]
然后使用下面的命令进行安装

1
2
LDFLAGS=-L$HOME/lib CPPFLAGS=-I$HOME/include ./configure --prefix=$HOME --with-tcsetpgrp
make && make instal

运行zsh发生如下错误

1
zsh --version

error while loading shared libraries: libncursesw.so.6: cannot open shared object file: No such file or directory

这个问题经过网络搜索,是由于执行zsh没有加载对应的动态库,因为我们的动态库安装在了我们自己的目录下面,通知执行下面的命令,即可得到解决

1
export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH

顺便把它加到.bash_profile里面吧,再次执行安装命令,即可安装完毕。

但是安装完 运行下面的命令

1
exec $HOME/bin/zsh -l 

会发生一直卡住不动,暂时不知道原因,哪位高手遇到解决了,可以留言给我,一起探讨。

最近使用主机发现,没有root权限,然后想用zsh,发现没有root权限也是安装不了,但是安装zsh又需要ncurses,但是网上都是一些yum之类的命令,但是yum只能root用哇,苦于无奈,只能安装在自己的目录下使用了。具体过程如下。

系统版本:

1
$ lsb_release -a

LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.3.1611 (Core)
Release: 7.3.1611
Codename: Core

源码包下载

http://ftp.gnu.org/pub/gnu/ncurses/
这里可以找到需要的版本

正常安装

1
./configure --prefix=$HOME

会遇到一个问题,如下

/usr/bin/ld: /usr/lib/libncurses.a(lib_addch.o): relocation R_X86_64_32 against a local symbol' can not be used when making a shared object; recompile with -fPIC /usr/lib/libncurses.a: could not read symbols: Bad value collect2: ld returned 1 exit status make[1]: \*\*\* [http://www.cnblogs.com/.ext/x86\_64-linux/curses.so] Error 1 make[1]: Leaving directory /home/deploy/tmp/ruby-
enterprise-1.8.6-20081215/source/ext/curses’
make: *** [all] Error 1

从错误中可以定位到可能是ncurses这个静态链接库的问题,从网上找了很久,解决方法如下在安装ncurses时如下方法安装:

1
2
$./configure --prefix=$HOME --with-shared --without-debug --enable-widec
$make && make install
0%