Ubuntu12.04下WordPress安装WP Super Cache后链接包含”%2F”导致分类链接返回404

WordPress安装WP Super Cache后需要开启"固定链接",但是开启之后,发现在点击分类链接的时候,一旦出现多页,点击分页的时候返回404错误。
开始认为是重写规则设置得不对, 后来才发现, 是"%2F"导致Apache直接返回404错误.

比如浏览查看某个标签下的文章列表的链接为

被重写后的URL变为:

这样"/"被替换为"%2F",当这个请求到达Apache的时候,被Apache直接返回404错误。
Apache有一个配置项"AllowEncodedSlashes", 默认是"Off", 也就是不允许请求路径(上例是 %2Fandroid/page/2)中包含编码后的斜杠'/'(在某些平台是反斜杠'\'). 这个选项的的相应代码在mod_rewrite模块被执行之前:

默认不允许包含"%2F". 如果请求路径中包含了, 那么ap_unescape_url()函数认为是无效的路径, 直接返回HTTP_NOT_FOUND, 最终浏览器得到的是"404 - Not Found"出错页面.

Apache的配置文件中增加AllowEncodedSlashes On即可.如下:

参考链接


链接包含"%2F"导致mod_rewrite失效

Windows下搭建基于Jenkins+Git+Gradle的Android持续集成

下载Jenkins


官网下载,如果官网下载存在问题,也可以在本站下载Jenkins

下载Gradle


目前Android Studio支持的是Gradle 2.8版本,因此下载2.8版本的即可。Gradle 2.8,也可以本站下载

安装Tomcat


官方主页Apache Tomcat。Windows下面建议下载32-bit/64-bit Windows Service Installer版本。
DownloadTomcat9

安装Jenkins


将下载的jenkins.war包直接放到tomcat下的webapps目录,启动tomcat,在浏览器输入:http://127.0.0.1:8080/jenkins

安装Git plugin,Gradle plugin,Android Lint Plugin插件


点击Jenkins首页的"Manage Jenkins"链接,如下图:
ManageJenkins

进入设置,点击"Manage Plugins",添加Git plugin,Gradle plugin,Android Lint Plugin

ManagePlugins在打开的页面中,搜索并且安装插件

PluginManagerInstall

系统配置


返回首页,点击" Manage Plugins",然后进入页面中选择Configure System,配置JDK,Gradle,Git的选项。

JenkinsConfigure
设置JDK
SettingJava

SettingJavaManual

新建项目


首页点击"创建一个新任务",如下图:
NewJenkinsJobs
在接下来的页面中,输入工程的名字,并且选择"Freestyle project"

NewJobsCreateSelect
设置Git中源代码的路径,如果是使用SSH证书认证的登陆,则在Credentials中进行配置,如下图:

JenkinsJobAndroidConfigureGitNew

接下来配置触发构建的条件,目前我们设置为每天晚上3点,注意里面输入的是H 3 * * *,每个字符之间都有一个英文的空格。

JenkinsJobAndroidConfigureTrigger

接下来,配置Gralde的编译,在构建项目中选择"Invoke Gradle Script",如下图:
InvokeGradleScript
在选项的Tasks栏目中输入clean build --stacktrace --debug,如下图:

InvokeGradleScriptTasks
接下来,配置构建后操作,一般增加Publish Android Lint results,Archive the artifacts这两项即可,具体的配置参考下图:

InvokeGradleScriptTasksAfterBuild

构建项目


BuildNow

检验构建结果


构建完成以后检查一下,如果在:

下面成功生成了APK文件,则说明配置是成功的。

参考链接


基于Jenkins+git+gradle的android持续集成,jenkinsgradle

TortoiseGit 与 Putty 配置冲突导致 Server refuse our key

TortoiseGitTortoiseSVNGit版本,TortoiseGit用于迁移TortoiseSVNTortoiseGit,一直以来GitWindows平台没有好用GUI客户端,现在TortoiseGit的出现给Windows开发者带来福音

TortoiseGit原本用得好好的,一日安装了Putty后,问题出现了。。

在进行git操作时提示:

TortoiseGit版本信息:

因为TortoiseGit调用了由Putty修改而来的TortoisePLink,因此Putty的配置将会影响TortoiseGit

解决方法,删除注册表中的以下节点即可:

参考链接:


TortoiseGit 与 Putty 配置冲突导致 Server refuse our key

Putty通过SSH无密码登陆Ubuntu12.04

(1)生成公钥/私钥对

注意"-P"后面输入的内容为空的时候代表不需要输入密码。
完成后会在当前用户目录下的.ssh目录下生成id_rsa,id_rsa.pub这两个文件。
(2)拷贝证书到本地机器
.ssh/id_rsa.pub拷贝下来,然后重命名成id_rsa.pub.git也就是Key加上用户名的命名方式,这样在Linux或者执行命令行的时候SSH可以自动进行用户名,密码的对应。
(3)对于Linux复制的id_rsa.pub.git添加到.ssh/authorzied_keys文件里

authorized_keys的权限要是600
(4)对于Windows,则需要把id_rsa这个文件拷贝下来,然后使用TortoiseGit自带的Puttygen转换为被TortoiseGit支持的.ppk文件。

点击"Conversions"菜单中的"Import key"选项,然后导入我们下载到的id_rsa

PuttyKeyGeneratorImportKey

导入后,

SavePPK

由于Puttygen的BUG,导致如果直接点击"Save private key",会导致生产的Public key是不正确的,因此,需要先点击"Save public key",保存为文件后,无视这个文件即可。然后接下来点击"Save private key"按钮,保存为.ppk文件,这个PPK文件才是我们需要的。

(5)修改SSHD的配置文件/etc/ssh/sshd_config
找到

这句,然后去掉注释。然后重启SSH服务

(6)修改登录认证文件,把认证信息导入到需要认证的用户目录下的.ssh/authorized_keys文件中。

以上面添加的用户git为例子,通过命令:

可以看到输出如下信息:

从而找到用户git的工作目录在/share目录下面.

因此执行如下命令:

接下来,需要修改authorized_keys的所有者为用户git,否则git无法通过这个文件进行认证。

而对于管理员root而言,我们不需要执行拷贝操作,只需要修改一下SSH的配置文件,并且执行如下命令即可:

(7)Putty设置使用PPK文件进行登陆认证

左侧栏中选择Connection->SSH->Auth:

LoginPPK
然后点击左侧栏中的Session,点击Save保存设置,然后点击Open连接服务器。
SaveSession

(8)登陆时候,还是需要输入用户名的,因为Ubuntu服务器需要根据用户名来核查证书。输入用户名后,直接回车,会发现不需要再输入密码,就直接登陆了。

putty-7

Android:flags:value

最近用到了Android flag的机制,把Android现在所有的flag列出来,供参考。

FLAG_GRANT_READ_URI_PERMISSION 0x00000001
FLAG_GRANT_WRITE_URI_PERMISSION 0x00000002
FLAG_FROM_BACKGROUND 0x00000004
FLAG_DEBUG_LOG_RESOLUTION 0x00000008
FLAG_EXCLUDE_STOPPED_PACKAGES 0x00000010
FLAG_INCLUDE_STOPPED_PACKAGES 0x00000020
FLAG_GRANT_PERSISTABLE_URI_PERMISSION 0x00000040
FLAG_GRANT_PREFIX_URI_PERMISSION 0x00000080
自定义 0x00000x00
自定义 0x00001000
FLAG_ACTIVITY_RETAIN_IN_RECENTS 0x00002000
FLAG_ACTIVITY_TASK_ON_HOME 0x00004000
FLAG_ACTIVITY_CLEAR_TASK 0x00008000
FLAG_ACTIVITY_NO_ANIMATION 0x00010000
FLAG_ACTIVITY_REORDER_TO_FRONT 0x00020000
FLAG_ACTIVITY_NO_USER_ACTION 0x00040000

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET 0x00080000
FLAG_ACTIVITY_NEW_DOCUMENT 0x00080000

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY 0x00100000
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 0x00200000
FLAG_ACTIVITY_BROUGHT_TO_FRONT 0x00400000
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 0x00800000
FLAG_ACTIVITY_PREVIOUS_IS_TOP 0x01000000
FLAG_ACTIVITY_FORWARD_RESULT 0x02000000
FLAG_ACTIVITY_CLEAR_TOP 0x04000000

FLAG_ACTIVITY_MULTIPLE_TASK 0x08000000
FLAG_RECEIVER_NO_ABORT 0x08000000

FLAG_RECEIVER_FOREGROUND 0x10000000
FLAG_ACTIVITY_NEW_TASK 0x10000000

FLAG_RECEIVER_REPLACE_PENDING 0x20000000
FLAG_ACTIVITY_SINGLE_TOP 0x20000000

FLAG_RECEIVER_REGISTERED_ONLY 0x40000000
FLAG_ACTIVITY_NO_HISTORY 0x40000000

Gradle build使用buildConfigField设置Log开关

应用场景


通常情况下我们的apps发布后也就是release模式下log是不显示的,debug模式下是显示log的,但是在特殊情况下我们测试release包的时候需要log的时候,就无法使用BuildConfig.DEBUG来达到要求,因为在release模式下自动设置为falsedebug模式下是true,这个时候我们需要自定义可控制的log开关。
Android Studio对应的BuildConfig.java位置

Studio中生成的目录: /app/build/generated/source/buildConfig/ 文件下的产品目录里面,找到想要的包名下会自动生成BuildConfig.java文件。我们可以看看下release模式下该文件的内容:

怎样自定义BuildConfig字段


在我们的build.gradle里面加入如下代码:


语法为:

上述语法就定义了一个boolean类型的LEO_DEBUG字段,值为true,之后我们就可以在程序中使用BuildConfig.LEO_DEBUG字段来判断我们所处的api环境。例如:

Ubuntu 12.04 系统下设置Tomcat 7服务器上JVM的内存大小

以前都是正常的Tomcat 7服务器,在增加了一个新工程后,无法正常访问,查看日志:

可以看到如下错误信息:

说明Tomcat在增加新工程后,内存不足了。

解决方法如下:

修改/etc/default/tomcat7文件:

找到如下信息:

可以看到,目前限制的内存最大值为128MB,-Xmx128m,调整到256MB后重启Tomcat7。

解决问题。

Node.js源码学习-模块

Node.js底层有三个重要部分

node

libuv 建立事件循环

v8 引擎以及JS/C++对象转换

node提供的模块 fs os net process等

libuv是一个神器,事件循环,适合状态机驱动的架构,单独学习。

v8的请看google的官方API文档。

今天主要看一下node的模块。

 

1.js2c.py

node内置了很多js文件,包括主程序 src/node.js和模块文件lib/*.js。js2py是把每一个js文件都生成一个源码数组,存放在node_natives.h中。

node_native

node_native.h中,每个js文件对应一个数组,源码以const char数组的形式存放。

 

node_native在映射完毕后,变成了这样一个数组。

2.node_javascript.cc

node_javascript.cc include了node_native.h,并提供两个方法:

MainSource(),只有一句

return OneByteString(env->isolate(), node_native, sizeof(node_native) - 1);

返回node_native映射的js文件,即node.js,转换成了一个v8::handle类型。node_native_1

 

 

图:node_native,node.js映射后的数组。

DefineJavaScript(env, target)

将所有js文件映射到Object型的target(不包括node.js)

target->Set(name, source)

综上,node_javascript.cc做了两件事,返回node.js的v8::handle,

返回lib/*.js的Object,{name: v8::handle, name: v8::handle .....}

现在所有js文件都被转换成了v8::handle。

3.node.cc

node.cc是nodejs的main文件,这里我们先认识一个node世界中的风云人物,process。

 

 

在node.cc的CreateEnvironment函数中,process出生了,下面我们从源码看看process是个什么?被赋予了哪些属性?

从上面这段代码可以看出process的原始属性,FunctionTemplate,很明显,是js里的一个function,function的name为process。

现在JS世界中已经多了一个叫process的function,那么它是在哪里成长的呢?

 

在node.cc的LoadEnvironment函数中,

运行MainSource

拿到了node.js的返回f_value,即node.js函数,入参为process的闭包函数,

(function(process) {})

验明正身,执行node.js闭包函数,最后一句做JS的同学看着肯定很眼熟,这不就是

(function(process){}).call(global, process)

 

4.fs.js

这里通过一个fs模块的创建与加载,来展示process呼风唤雨的能力。

首先规规矩矩的加载了几个模块,然后突然出现了binding

Binding在node.cc中实现

主要逻辑为,查看cache中是否有这个模块,如果没有就新建一个。

新建模块:如果存在builtin,则使用nm_context_register_func方法注册到cache中,如果是常量,cache中注册常量,如果是natives,绑定所有lib/*.js。

在fs中,process.binding找到了fs,是一个builtin模块。这个模块在node_file.cc中实现,最后通过NODE_MODULE_CONTEXT_AWARE_BUILTIN注册到builtin。

Binding函数完成了js上调用C++模块。

 

5.node.js

node.js中通过一个NativeModules来管理js模块,

 

process.binding('natives'),将所有内置js模块绑定到_source上。

之后可以通过require方法来拿到这些模块。

先检查cache,如果cache没有,就在process.moduleLoadList中增加一个,然后缓存,执行.

缓存就是把模块放到_cache中,compile函数

通过C++模块contextify运行了这段js。