# 常用命令介紹
> ## 指令
#### **lua\_code\_cache**_** **on \| off;_
**作用:**打開或關閉 Lua 代碼緩存,影響以下指令: set\_by\_lua\_file , content\_by\_lua\_file, rewrite\_by\_lua\_file, access\_by\_lua\_file 及強制加載或者reload Lua 模塊等.緩存開啟時修改LUA代碼需要重啟nginx,不開啟時則不用。開發階段一般關閉緩存。
**作用域:**main, server, location, location if
---
#### **lua\_package\_path **_** **../path... ;_
**作用:**設置用lua代碼寫的擴展庫路徑。
**例:**lua\_package\_path '/foo/bar/?.lua;/blah/?.lua;;';
---
#### **lua\_package\_cpath **_'/bar/baz/?.so;/blah/blah/?.so;;';_
**作用:**設置C擴展的lua庫路徑。
---
#### **set\_by\_lua **_$var '<lua-script>' \[$arg1 $arg2\];_
#### set\_by\_lua\_file _$var <path-to-lua-script-file> \[$arg1 $arg2 ...\];_
**作用:**設置一個Nginx變量,變量值從lua腳本里運算由return返回,可以實現復雜的賦值邏輯;此處是阻塞的,Lua代碼要做到非常快.另外可以將已有的ngx變量當作參數傳進Lua腳本里去,由ngx.arg\[1\],ngx.arg\[2\]等方式訪問。
**作用域:**main, server, location, server if, location if
**處理階段:**rewrite
---
#### content\_by\_lua _'<lua script>'; _
#### content\_by\_lua\_file _luafile;_
**作用域:**location, location if
**說明:**內容處理器,接收請求處理并輸出響應,content\_by\_lua直接在nginx配置文件里編寫較短Lua代碼后者使用lua文件。
---
#### rewrite\_by\_lua _'<lua script>' _
#### rewrite\_by\_lua\_file _lua\_file;_
**作用域:**http, server, location, location if
執行內部URL重寫或者外部重定向,典型的如偽靜態化的URL重寫。其默認執行在rewrite處理階段的最后.
注意,在使用rewrite\_by\_lua時,開啟rewrite\_log on;后也看不到相應的rewrite log。
---
#### **access\_by\_lua **_'lua code';_
#### **access\_by\_lua\_file**_** **lua\_file.lua;_
作用:用于訪問控制,比如我們只允許內網ip訪問,可以使用如下形式。
```lua
access_by_lua '
if ngx.req.get_uri_args()["token"] ~= "123" then
return ngx.exit(403)
end ';
```
**作用域:**http, server, location, location if
---
#### **header\_filter\_by\_lua **_'lua code';_
#### **header\_filter\_by\_lua\_file **_path\_file.lua;_
作用:設置header 和 cookie;
---
#### **init\_by\_lua **_** **'lua code';_
#### **init\_by\_lua\_file **_** **lua\_file.lua;_
**作用域:**http
**說明**:ginx Master進程加載配置時執行;通常用于初始化全局配置/預加載Lua模塊
---
#### **init\_worker\_by\_lua **_'lua code';_
#### **init\_worker\_by\_lua\_file **_luafile.lua;_
**作用域:**http
**說明:**每個Nginx Worker進程啟動時調用的計時器,如果Master進程不允許則只會在init\_by\_lua之后調用;通常用于定時拉取配置/數據,或者后端服務的健康檢查。
> ## 方法和常量
```nginx
ngx.arg[index] #ngx指令參數,當這個變量在set_by_lua或者set_by_lua_file內使用的時候是只讀的,指的是在配置指令輸入的參數.
ngx.var.varname #讀寫NGINX變量的值,最好在lua腳本里緩存變量值,避免在當前請求的生命周期內內存的泄漏
ngx.config.ngx_lua_version #當前ngx_lua模塊版本號
ngx.config.nginx_version #nginx版本
ngx.worker.exiting #當前worker進程是否正在關閉
ngx.worker.pid #當前worker進程的PID
ngx.config.nginx_configure #編譯時的./configure命令選項
ngx.config.prefix #編譯時的prefix選項
core constans: #ngx_lua 核心常量
ngx.OK (0)
ngx.ERROR (-1)
ngx.AGAIN (-2)
ngx.DONE (-4)
ngx.DECLINED (-5)
ngx.nil
http method constans: #經常在ngx.location.catpure和ngx.location.capture_multi方法中被調用.
ngx.HTTP_GET
ngx.HTTP_HEAD
ngx.HTTP_PUT
ngx.HTTP_POST
ngx.HTTP_DELETE
ngx.HTTP_OPTIONS
ngx.HTTP_MKCOL
ngx.HTTP_COPY
ngx.HTTP_MOVE
ngx.HTTP_PROPFIND
ngx.HTTP_PROPPATCH
ngx.HTTP_LOCK
ngx.HTTP_UNLOCK
ngx.HTTP_PATCH
ngx.HTTP_TRACE
http status constans: #http請求狀態常量
ngx.HTTP_OK (200)
ngx.HTTP_CREATED (201)
ngx.HTTP_SPECIAL_RESPONSE (300)
ngx.HTTP_MOVED_PERMANENTLY (301)
ngx.HTTP_MOVED_TEMPORARILY (302)
ngx.HTTP_SEE_OTHER (303)
ngx.HTTP_NOT_MODIFIED (304)
ngx.HTTP_BAD_REQUEST (400)
ngx.HTTP_UNAUTHORIZED (401)
ngx.HTTP_FORBIDDEN (403)
ngx.HTTP_NOT_FOUND (404)
ngx.HTTP_NOT_ALLOWED (405)
ngx.HTTP_GONE (410)
ngx.HTTP_INTERNAL_SERVER_ERROR (500)
ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)
ngx.HTTP_SERVICE_UNAVAILABLE (503)
ngx.HTTP_GATEWAY_TIMEOUT (504)
Nginx log level constants: #錯誤日志級別常量 ,這些參數經常在ngx.log方法中被使用.
ngx.STDERR
ngx.EMERG
ngx.ALERT
ngx.CRIT
ngx.ERR
ngx.WARN
ngx.NOTICE
ngx.INFO
ngx.DEBUG
##################
#API中的方法:
##################
print() #與 ngx.print()方法有區別,print() 相當于ngx.log()
ngx.ctx #這是一個lua的table,用于保存ngx上下文的變量,在整個請求的生命周期內都有效,詳細參考官方
ngx.location.capture() #發出一個子請求,詳細用法參考官方文檔。
ngx.location.capture_multi() #發出多個子請求,詳細用法參考官方文檔。
ngx.status #讀或者寫當前請求的相應狀態. 必須在輸出相應頭之前被調用.
ngx.header.HEADER #訪問或設置http header頭信息,詳細參考官方文檔。
ngx.req.set_uri() #設置當前請求的URI,詳細參考官方文檔
ngx.set_uri_args(args) #根據args參數重新定義當前請求的URI參數.
ngx.req.get_uri_args() #返回一個LUA TABLE,包含當前請求的全部的URL參數
ngx.req.get_post_args() #返回一個LUA TABLE,包括所有當前請求的POST參數
ngx.req.get_headers() #返回一個包含當前請求頭信息的lua table.
ngx.req.set_header() #設置當前請求頭header某字段值.當前請求的子請求不會受到影響.
ngx.req.read_body() #在不阻塞ngnix其他事件的情況下同步讀取客戶端的body信息.[詳細]
ngx.req.discard_body() #明確丟棄客戶端請求的body
ngx.req.get_body_data() #以字符串的形式獲得客戶端的請求body內容
ngx.req.get_body_file() #當發送文件請求的時候,獲得文件的名字
ngx.req.set_body_data() #設置客戶端請求的BODY
ngx.req.set_body_file() #通過filename來指定當前請求的file data。
ngx.req.clear_header() #清求某個請求頭
ngx.exec(uri,args) #執行內部跳轉,根據uri和請求參數
ngx.redirect(uri, status) #執行301或者302的重定向。
ngx.send_headers() #發送指定的響應頭
ngx.headers_sent #判斷頭部是否發送給客戶端ngx.headers_sent=true
ngx.print(str) #發送給客戶端的響應頁面
ngx.say() #作用類似ngx.print,不過say方法輸出后會換行
ngx.log(log.level,...) #寫入nginx日志
ngx.flush() #將緩沖區內容輸出到頁面(刷新響應)
ngx.exit(http-status) #結束請求并輸出狀態碼
ngx.eof() #明確指定關閉結束輸出流
ngx.escape_uri() #URI編碼(本函數對逗號,不編碼,而php的urlencode會編碼)
ngx.unescape_uri() #uri解碼
ngx.encode_args(table) #將tabel解析成url參數
ngx.decode_args(uri) #將參數字符串編碼為一個table
ngx.encode_base64(str) #BASE64編碼
ngx.decode_base64(str) #BASE64解碼
ngx.crc32_short(str) #字符串的crs32_short哈希
ngx.crc32_long(str) #字符串的crs32_long哈希
ngx.hmac_sha1(str) #字符串的hmac_sha1哈希
ngx.md5(str) #返回16進制MD5
ngx.md5_bin(str) #返回2進制MD5
ngx.today() #返回當前日期yyyy-mm-dd
ngx.time() #返回當前時間戳
ngx.now() #返回當前時間
ngx.update_time() #刷新后返回
ngx.localtime() #返回 yyyy-mm-dd hh:ii:ss
ngx.utctime() #返回yyyy-mm-dd hh:ii:ss格式的utc時間
ngx.cookie_time(sec) #返回用于COOKIE使用的時間
ngx.http_time(sec) #返回可用于http header使用的時間
ngx.parse_http_time(str) #解析HTTP頭的時間
ngx.is_subrequest #是否子請求(值為 true or false)
ngx.re.match(subject,regex,options,ctx) #ngx正則表達式匹配,詳細參考官網
ngx.re.gmatch(subject,regex,opt) #全局正則匹配
ngx.re.sub(sub,reg,opt) #匹配和替換(未知)
ngx.re.gsub() #未知
ngx.shared.DICT #ngx.shared.DICT是一個table 里面存儲了所有的全局內存共享變量
ngx.shared.DICT.get
ngx.shared.DICT.get_stale
ngx.shared.DICT.set
ngx.shared.DICT.safe_set
ngx.shared.DICT.add
ngx.shared.DICT.safe_add
ngx.shared.DICT.replace
ngx.shared.DICT.delete
ngx.shared.DICT.incr
ngx.shared.DICT.flush_all
ngx.shared.DICT.flush_expired
ngx.shared.DICT.get_keys
ndk.set_var.DIRECTIVE #不懂
```
> ## 方法詳細介紹
### ngx.arg
> 語法:val = ngx.arg \[index\]
上下文:set\_by\_lua \*,body\_filter\_by\_lua \*
描述:當在set\_by\_lua \*指令的上下文中使用時,此表是只讀的,并保存config指令的輸入參數:
```lua
value = ngx.arg[n]
```
例子:
```nginx
location /foo_sum {
default_type text/html;
set $a 32;
set $b 56;
set_by_lua $sum
'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])' $a $b;
echo "sum = ${sum}";
}
```
## ngx.location.capture
> 語法: _res = ngx.location.capture\(uri, options?\)_
上下文: _rewrite\_by\_lua \*,\* access\_by\_lua,content\_by\_lua \*_
是一個同步非阻塞的NGINX子請求uri
NGINX的子請求提供了一個非常強大的方式去實現非阻塞的內部請求,或者其他的C模塊,比如 ngx\_proxy, ngx\_fastcgi, ngx\_memc, ngx\_postgres, ngx\_drizzle, 甚至ngx\_lua自己等等。
當然,這些子請求僅僅是模擬HTTP請求,但是并沒有額外的 HTTP/TCP,所有的進程都是C級別的
子請求完全不同與HTTP 301/302。
這里有個基本的例子:
```nginx
res = ngx.location.capture(uri)
```
返回與4插槽,一個Lua表:`res.status`,`res.header`,`res.body`,和`res.truncated`。
`res.status` 用于保存子請求響應的響應狀態代碼。
`res.header`持有子請求的響應頭,這是一個正常的Lua表。對于多值響應頭,該值是保存所有的順序它們出現的值的Lua(陣列)表。例如,如果子請求響應報頭包含以下幾行:
返回一個LUA的TABLE,三個值\(res.status, res.header, and res.body\)。
res.header包含了所有的子請求的頭的信息,它是一個普通的LUA TABLE。比如多個值的相應頭,他們以數組的形式按照順序返回出現。例如:子請求包含了如下信息:
```nginx
Set-Cookie: a=3
Set-Cookie: foo=bar
Set-Cookie: baz=blah
```
然后`res.header["Set-Cookie"]`將被評估,以表中的值 `{"a=3", "foo=bar", "baz=blah"}`。
`res.body`持有子請求的響應體數據,這些數據可能會被截斷。你總是需要檢查
`res.truncated`布爾標志,看是否`res.body`包含截斷數據。這里的數據截斷只能由那些不可恢復的錯誤在你的子請求一樣,遠端中止在響應體數據流的中間,或當你的子請求接收從響應體數據的讀取超時發生過早的連接的情況下造成的遙控器。URI查詢串可以串聯到的URI本身,例如:
```nginx
res = ngx.location.capture('/foo/bar?a=3&b=4')
```
像名為位置`@foo`不允許由于nginx的核心的限制。使用與組合正常位置`internal`指令準備僅供內部使用的位置。
可選選項表可以喂的第二個參數,它支持的選項:
* `method`
指定子請求的請求方法,只接受常量一樣`ngx.HTTP_POST`。
* `body`
指定子請求的請求體(僅字符串值)。
* `args`
指定子請求的URI查詢參數(這兩個字符串值和Lua表被接受)
* `ctx`
指定一個Lua表是[ngx.ctx](https://github.com/openresty/lua-nginx-module#ngxctx)為子請求表。它可以是當前請求的[ngx.ctx](https://github.com/openresty/lua-nginx-module#ngxctx)表,這有效地使母體和其子請求共享完全相同的上下文表。此選項最初是在引進`v0.3.1rc25`發行。
* `vars`
采取持有的值設置指定的Nginx變量在子請求作為此選項的值一個Lua表。此選項最初是在引進`v0.3.1rc31`
發行。
* `copy_all_vars`
指定是否在當前請求所討論的子請求的所有的Nginx變量值復制。在子請求nginx的變量的修改將不會影響當前(父)的請求。此選項最初是在引進`v0.3.1rc31`發行。
* `share_all_vars`
指定是否共享的子請求與當前(父)要求所有的Nginx變量。在子請求Nginx的變量的修改將影響當前(父)的請求。啟用此選項可能會導致因不良副作用難以調試問題,被認為是不好的,有害的。只有啟用該選項,當你完全知道自己在做什么。
* `always_forward_body`
當設置為true,當前(父)的請求的請求體總是會被轉發到,如果創建的子請求`body`未指定選項。無論是通過讀取請求體
[()ngx.req.read\_body](https://github.com/openresty/lua-nginx-module#ngxreqread_body)或[lua\_need\_request\_body上](https://github.com/openresty/lua-nginx-module#lua_need_request_body)會被直接轉發到子請求不創建子請求(無論請求體數據在內存中緩存或臨時文件緩存)時復制整個請求體數據。默認情況下,這個選項是`false`和時`body`
沒有指定選項時,當前的(父)請求的請求體,當子請求取只轉發`PUT`或`POST`請求方法。
發出一個POST子請求,例如,可以做如下:
```nginx
res = ngx.location.capture(
'/foo/bar',
{ method = ngx.HTTP_POST, body = 'hello, world' }
)
```
看到比其他POST HTTP方法的常量方法。該`method`選項是`ngx.HTTP_GET`默認。
該`args`選項可以指定額外的URI參數,例如:
```nginx
ngx.location.capture('/foo?a=1',
{ args = { b = 3, c = ':' } }
)
```
相當于
```nginx
ngx.location.capture('/foo?a=1&b=3&c=%3a')
```
也就是說,該方法將根據規則URI參數逃脫鍵和值一起將它們連接起來成為一個完整的查詢字符串。對于作為通過的Lua表的格式`args`參數是相同于使用的格式[ngx.encode\_args](https://github.com/openresty/lua-nginx-module#ngxencode_args)方法。該`args`選項也可以采取簡單的查詢字符串:
```lua
ngx.location.capture('/foo?a=1',
{ args = 'b=3&c=%3a' } }
)
```
這在功能上等同于前面的例子。
該`share_all_vars`
選項控制是否將當前請求和子請求之間共享nginx的變量。如果此選項設置為`true`
,那么當前請求和相關的子請求將共享相同的Nginx變量的作用域。因此,通過一個子請求更改了Nginx的變量將影響到當前的請求。
應小心使用此選項,變量的作用域共享可以有意想不到的副作用。的`args`,`vars`或`copy_all_vars`選項通常優于代替。這個選項被設置為`false`默認.
```nginx
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua_block {
res = ngx.location.capture("/other",
{ share_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
}
}
```
訪問位置`/lua`給:
```nginx
/other dog: hello world
/lua: hello world
```
該`copy_all_vars`選項提供父請求的Nginx的變量的副本子請求時這樣子請求發出。由這樣子請求對這些變量所做的更改不會影響父請求或任何其他子請求共享父請求的變量。
```nginx
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua_block {
res = ngx.location.capture("/other",
{ copy_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
}
}
```
請求`GET /lua`將給輸出
```nginx
/other dog: hello world
/lua: hello
```
請注意,如果兩者`share_all_vars`并`copy_all_vars`都設置為true,則`share_all_vars`優先。
除了上述兩個設置,有可能使用在子請求變量的值`vars`選項。這些變量的變量共享或復制已評估后設置,并且提供了對編碼它們以URL參數,并在Nginx的配置文件反向轉義它們傳遞特定值應用于一個子請求的更有效的方法:
```nginx
location /other {
content_by_lua_block {
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
}
}
location /lua {
set $dog '';
set $cat '';
content_by_lua_block {
res = ngx.location.capture("/other",
{ vars = { dog = "hello", cat = 32 }});
ngx.print(res.body)
}
}
```
訪問`/lua`將產生的輸出:
```nginx
dog = hello
cat = 32
```
該`ctx`選項可用于指定自定義的Lua表作為[ngx.ctx](https://github.com/openresty/lua-nginx-module#ngxctx)為子請求表.
```nginx
location /sub {
content_by_lua_block {
ngx.ctx.foo = "bar";
}
}
location /lua {
content_by_lua_block {
local ctx = {}
res = ngx.location.capture("/sub", { ctx = ctx })
ngx.say(ctx.foo);
ngx.say(ngx.ctx.foo);
}
}
```
然后請求`GET /lua 輸出:`
```lua
bar
nil
```
另外,也可以使用這個`ctx`選項共享同一[ngx.ctx](https://github.com/openresty/lua-nginx-module#ngxctx)電流(父)請求和子請求之間的表:
```nginx
location /sub {
content_by_lua_block {
ngx.ctx.foo = "bar";
}
}
location /lua {
content_by_lua_block {
res = ngx.location.capture("/sub", { ctx = ngx.ctx })
ngx.say(ngx.ctx.foo);
}
}
```
請求`GET /lua`產生的輸出:bar
- 1 Lua介紹及環境
- 2 基本語法
- 3 數據類型
- 4 Lua 變量
- 5 循環
- 6 流程控制
- 7 函數
- 8 運算符
- 9 字符串
- 10 數組
- 11 迭代器
- 12 table
- 13 Lua 模塊與包
- 14 Lua 元表(Metatable)
- 14.1 元表案例
- 15 Lua 協同程序(coroutine)
- 16 Lua 文件IO
- 17 Lua 面向對象
- 17.1 類
- 17.2 繼承
- 17.3 封裝
- 18 Lua 與 Mysql
- 19 Lua 與 redis
- 20 Lua 與 JSON
- 21 Lua 與 http
- 22 Lua 與 Nginx
- 22.1 Nginx_Lua的安裝及環境
- 22.2 ngx_lua API(全表)
- 22.3 常用命令介紹
- 22 Lua 人工智能
- (1) Torch的安裝
- (2)Tensor
- Lua與C混合編程