自动摘要
正在生成中……
最近安装了openresty
,想做一个通过git各大代码托管平台提供的webhook
实现自动部署的功能。以前的实现方式是服务器暴露一个接口(php写的)给托管平台,webhook
访问后接口会做一个修改或更新文件的动作,同时服务器上部署一个监控该文件的脚本,一旦检测到文件更新就调用系统的命令,比如 git pull
及其他命令进行项目更新和构建。
为什么不直接通过php来调用系统命令而单独写一个监控脚本呢?
首先是权限的问题,php无论是以php-fpm
还是apache模块,一般都会用单独的用户来运行,这是出于安全的考虑,这个用户对项目目录也没有写入的权限,除了部分特殊的目录,比如上传目录才有写权限。所以远程仓库的更新没有办法直接写入到本地。
其次也是因为安全的原因,线上服务器的php.ini
的设定都会禁用危险的 exec
、system
之类的用来调用shell
命令的函数。
关于监控脚本
windows
上可以写一个批处理并加入开机启动,linux
上有inotify
,后来我还发现了可以使用nodemon
实现跨平台。很多人对nodemon
的印象还是停留在 javascript
上面,特别是前端开发和node.js
用得比较多,其实它也可以执行非js文件,比如shell script,python 脚本等等,非常好用的一个工具。
为什么用openresty/ngx_lua
上面的解决方案的缺点很明显,又是php
,又是nodemon
,还要指定一个监控文件,要依赖的东西太多了,结构上非常松散,也不利于迁移和重用,但是如果用openresty, 只要集中在lua脚本就可以了,加上少量的nginx配置,如果简单粗暴一些,甚至可以直接写在nginx配置里。
怎么做?
- 下载安装麻省理工Juce版的 lua_resty_shell
- 下载安装 sockproc
- 编写lua脚本
openresty
有一个默认lualib
目录,在 MacOS 上位于 /usr/local/Cellar/openresty/1.19.3.1_1/lualib
,这个目录的作用是如果脚本里要引用一个包,比如require "resty.shell"
,映射到磁盘的文件,点会被转化为“/
”,lua
会在此目录搜索搜索并实际匹配到这个文件:/usr/local/Cellar/openresty/1.19.3.1_1/lualib/resty/shell.lua
你可以直接把 juce版lua_resty_shell
克隆下来并将 shell.lua
文件放入默认的lualib目录,不过这样会替换掉openresty自带的 resty/shell
模块,不建议这样做,可以建立一个单独的目录,这里是用 /Users/falcon/projects/lua/lualib
用来存放用户或者第三方的package
,把前面的shell.lua
放在这个目录,同时修改nginx.conf
,http
加入以下内容:
http {
lua_code_cache off; # 仅开发环境禁用
lua_package_path "/Users/falcon/projects/lua/lualib/?.lua;;";
...
lua_package_path
指令表示lua包搜索的路径,;;
表示默认路径。?
就是require
里引用模块的名称,在上文指的是 resty/shell
。关于 lua_package_path
更多的内容可以参考这篇文章。
按照文档下载编译并启动,可以监听socket,也可以监听端口。btw,我看了文档才知道原来 Macos 上的 telnet
命令是可以按socket来连接的,比linux上的 telnet
可要多才多艺(versatile)?, linux 上的只能通过端口连接,要连接socket可以通过socat
。
为了方便,我写了个几行小脚本启动:
#!/usr/bin/env bash
/bin/rm /tmp/shell.sock >/dev/null 2>&1
/Users/falcon/cmd/sockproc/sockproc /tmp/shell.sock
3. 编写lua脚本
建立项目路径:/Users/falcon/projects/lua/ngx_script
, 新增 test-shell.lua
local shell = require "resty.shell"
local args = {
socket = "unix:/tmp/shell.sock", -- 这是第一步的 unxi socket
}
local status, out, err = shell.execute("uptime", args) -- ls 是想调用的命令,
ngx.header.content_type = "text/plain"
ngx.say("Result:\n" .. out) -- 命令输出结果
修改nginx.conf
,server块:
server {
listen 80 default_server;
server_name localhost;
location = /shell {
default_type 'text/html';
content_by_lua_file /Users/falcon/projects/lua/ngx_script/test-shell.lua;
}
}
重启openresty, 访问 http://localhost/shell 会看到以下内容,跟在终端里调用 uptime
命令结果是一样的
Result:
19:28 up 19:57, 3 users, load averages: 2.50 2.98 3.30
说明调用 shell
的测试成功,下面开始编写构建项目自动更新的脚本。
@to-be-continue