nginx的脚本引擎(一)
nginx的脚本的语法和shell是很像的,我大致看了一下觉得挺有意思的,就想写写记录一下。我没看过shell脚本的引擎,不知道nginx脚本引擎和shell脚本引擎像不像,但是我觉得nginx的脚本引擎有点像C和汇编。

ngx_http_script_engine_t这个结构就代表了一段脚本,ip指向的是编译好的脚本,sp指向的是一块内存用来存储脚本运行的时候产生的一些中间值。ip/sp从名字看就已经很像汇编了instruction pointer/stack pointer指令寄存器和栈寄存器呀,当然是我瞎猜的,有时间的话可以查一下官方文档。代码段里的各个指令长度不一定相同。
再来说说编译过程,编译过程是在nginx_http_script_engine_t建立之前执行的,我先画出了整个图是为了更好理解。举个set指令编译的的例子,比如你在脚本里有这样的代码set $foo helloworld,脚本编译的步骤如下:
第一步:首先在cmcf->variables_keys和cmcf->variables里增加一个变量foo,这个变量是可写的。我之前写的nginx的变量系统里只说了变量的读取方法,差别不大。
第二步:把ngx_http_script_value_code_t指令放到代码段里(code字段是一个回调函数,赋值成ngx_http_script_value_code),把ngx_http_script_var_code_t指令放到代码段里(code字段是一个回调函数,赋值成ngx_http_script_set_var_code)。
第三步:http请求来的时候会在rewrite阶段按顺序执行ip指向的这一段代码,也就是执行ngx_http_script_value_code和ngx_http_script_set_var_code函数。
我们看一下这两个函数做了什么
void
ngx_http_script_value_code(ngx_http_script_engine_t *e)
{
ngx_http_script_value_code_t *code; code = (ngx_http_script_value_code_t *) e->ip; e->ip += sizeof(ngx_http_script_value_code_t); e->sp->len = code->text_len;
e->sp->data = (u_char *) code->text_data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script value: \"%v\"", e->sp); e->sp++;
}
void
ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
{
ngx_http_request_t *r;
ngx_http_script_var_code_t *code; code = (ngx_http_script_var_code_t *) e->ip; e->ip += sizeof(ngx_http_script_var_code_t); r = e->request; e->sp--; r->variables[code->index].len = e->sp->len;
r->variables[code->index].valid = 1;
r->variables[code->index].no_cacheable = 0;
r->variables[code->index].not_found = 0;
r->variables[code->index].data = e->sp->data;
}
第一条指令把“helloworld”这个字符串放到了sp里,第二条指令把值从sp里取出来存到了变量系统的foo变量里,任务完成,看起来很简单。
set指令还可以这样用set $foo $x$y,这就是所谓的变量插值,过程和上面这个类似,只不过第一条指令是先从变量系统里取出$x和$y的值,再放入sp里。
其他指令和set指令的执行过程类似,把我看到的也写一下吧
if指令:同样举个最简单的例子if( $host = "www.foo.com" ),编译的时候依次把ngx_http_script_var_code/ngx_http_script_value_code_t/ngx_http_script_equal_code/ngx_http_script_if_code四条指令放到代码段里。脚本运行的时候这几条指令的工作分别是ngx_http_script_var_code把变量host的值取出来放到sp里。ngx_http_script_value_code_t把字符串“www.foo.com”放到sp里。ngx_http_script_equal_code比较sp里存的两个值是否相等并把两个值清除掉,相等就在sp里写入“1”,不相等就写入“0”(比较完以后这两个值就没用了,清除掉这两个值并且写入结果很像C里函数调用的过程)。ngx_http_script_if_code检查sp里的值是不是“0”,不是“0”说明条件为真继续执行之后的脚本,是“0”说明条件为假就会跳过这一段代码执行ngx_http_script_if_code_t结构里next偏移之后的代码。所有的代码都是在一个代码段里,不会因为有if把代码做嵌套,只不过会用next跳来跳去。
有一点需要注意如果if在location里if体里可以做一些location的配置,比如root之类的。当NGX_HTTP_REWRITE_PHASE阶段执行脚本的时候会把新的loc_conf赋值给r->loc_conf,这个一定要注意是NGX_HTTP_REWRITE_PHASE阶段而不是NGX_HTTP_FIND_CONFIG_PHASE阶段,设置loc_conf一般情况是在NGX_HTTP_FIND_CONFIG_PHASE阶段,但是这次不是。
void
ngx_http_script_if_code(ngx_http_script_engine_t *e)
{
ngx_http_script_if_code_t *code; code = (ngx_http_script_if_code_t *) e->ip; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script if"); e->sp--; if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) {
if (code->loc_conf) {
e->request->loc_conf = code->loc_conf;
ngx_http_update_location_config(e->request);
} e->ip += sizeof(ngx_http_script_if_code_t);
return;
} ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script if: false"); e->ip += code->next;
}
return指令:这个是比较简单的,脚本执行到这个指令就直接返回了,参数了可以带数据,例如return 200 helloworld,此外还可以重定向return 302 http://www.nginx.org。
break指令:粗暴的结束目前的脚本,但是有一点要注意,如果break指令在location里面,他并不会影响location其他字段的设置,因为他们在不同的阶段执行。比如说设置如下的配置文件
location / {
root html;
break;
index index.html;
}
这一点都不会影响你的index指令,他们不在同一阶段,index是在NGX_HTTP_FIND_CONFIG_PHASE阶段,break是在NGX_HTTP_REWRITE_PHASE阶段,就像if指令里说的那样。
rewrite指令:这个略显麻烦,但是道理是一样的,休息,明天接着写。
nginx的脚本引擎(一)的更多相关文章
- nginx的脚本引擎(二)rewrite
其实rewrite指令和上一篇说的if/set/return/break之类的没多大差别,但是rewrite用起来相对复杂,我就把他单独放到了这里.想要弄懂nginx的脚本引擎需要先明白处理reque ...
- Java 8 的 Nashorn 脚本引擎教程
本文为了解所有关于 Nashorn JavaScript 引擎易于理解的代码例子. Nashorn JavaScript 引擎是Java SE 8的一部分,它与其它像Google V8 (它是Goog ...
- 【开源】.Net 动态脚本引擎NScript
开源地址: https://git.oschina.net/chejiangyi/NScript 开源QQ群: .net 开源基础服务 238543768 .Net 动态脚本引擎 NScript ...
- [No00007A]没有文件扩展".js"的脚本引擎 解决办法
在命令行运行JScript脚本时,遇到如下的错误提示: “输入错误: 没有文件扩展“.js”的脚本引擎.” 这样的错误,原因是因为JS扩展名的文件被其他软件关联了,需要取消关联. 如系统中安装了ULT ...
- 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
- linux nginx 启动脚本
linux nginx 启动脚本 [root@webtest76 ~]# vi /etc/init.d/nginx #!/bin/bash # nginx Startup script for the ...
- cocos2dx的build_win32.dat出现问题以及install-template-msvc.dat出现.js没有脚本引擎
关于cocos2dx-2.x.x版本当中出现build_win32.bat执行失败 (针对VS2013)应当在VS的安装路径查找msbuild的文件夹,再其中查找msbuild.exe文件找到四个东西 ...
- c# 动态执行脚本,相关的几个脚本引擎.
Jint 嵌入式的javascript脚本支持引擎,一直都在更新,对各种方法支持也比较好,可以 C# 交互. https://github.com/sebastienros/jint Jurass ...
- Nginx+Keepalived(带Nginx监控脚本)
转载于:http://www.itxuexiwang.com/a/liunxjishu/2016/0220/151.html?1456381460 Keepalived+ nginx的安装部署 主机: ...
随机推荐
- 项目中使用mybatis报错:对实体 "serverTimezone" 的引用必须以 ';' 分隔符结尾。
报错信息如下: Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: ### ...
- 【Java/DateTime】用当前日期时间与确定日期时间比较,大于则执行某动作
代码: package logbackCfg; import java.text.ParseException; import java.text.SimpleDateFormat; import j ...
- JAVA实现汉字转拼音
两个工具包都可以实现:pinyin4j/JPinyin pinyin4j 第一个是使用pinyin4j的jar,此jar对多音字语句的处理不太理想 package edu.ws; import net ...
- 原生JDK网络编程BIO
服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信. 传统的同步阻塞模型开发中,ServerSocket负责绑 ...
- Solr专题(三)SSM项目整合Solr
一.环境配置 所需要的jar包: org.apache.solr.solr-solrj maven依赖: <!-- https://mvnrepository.com/artifact/org. ...
- 安装python3,配置pycharm
1.下载最新版python3 首先去python官网下载python3的源码包,网址:https://www.python.org/ 进去之后点击导航栏的Downloads,也可以鼠标放到Downlo ...
- [LeetCode]面试题14- I. 剪绳子(DP/贪心)
题目 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m.n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m] .请问 k[0]k[1]...* ...
- Git进阶:常用命令和问题案例整理
一.前言 整理常用git命令和以及在实际使用的过程中碰到的问题案例,旨在git进阶,提升工作开发效率,有需要补充的小伙伴欢迎下方留言,本篇持续更新中... 二.命令 配置用户名和邮箱 git conf ...
- 算法数据结构 | 三个步骤完成强连通分量分解的Kosaraju算法
强连通分量分解的Kosaraju算法 今天是算法数据结构专题的第35篇文章,我们来聊聊图论当中的强连通分量分解的Tarjan算法. Kosaraju算法一看这个名字很奇怪就可以猜到它也是一个根据人名起 ...
- Oracle sqlplus中退格键、DEL键、上下左右键无法使用乱码问题
功能描述:Oracle sqlplus中退格键.DEL键.上下左右键无法使用乱码 1.安装readline-8.0 ①下载readline-8.0.tar.gz文件,百度网盘下载路径: https:/ ...