周りのマークアップエンジニアがgit使いこなしていて、平気でブランチを切り替えたりして開発サーバー上で作業して貰っています。ただし、ブランチ切り変えになると、たまにアプリリスタートも必要で、マークアップじゃ一人で作業したいブランチを開発サーバーに反映できない場合があります。
Plack::Loader::Shotgunを使ってアプリさえ実行すれば、こういった問題をよりやすく解決できる気もしますが、一応、Nginx OpenRestyを使ってみたかったので、試しにウェブインタフェースを使ってプロセスをリスタートできるアプリを作っちゃいました。
*OpenRestyについてはOpenRestyの公式ページを参考にしてください
**フレームワークはLapisというOpenResty上で動くLuaのウェブフレームワークです。おしゃんてぃでおすすめです。
最近process管理のため主にSupervisordを使っています。周りの人がそれをrootを使って実行しガチなんですが、やっぱり開発環境といってもウェブのユーザがrootのプロセスが実行できたら怖いですし、nginx自体も普段nobodyユーザによって実行されるので、まずSupervisordをnobodyユーザとして実行しました。 そこでnobodyがアクセスできるディレクトリを作って、以下のlapis app.luaを作成しました:--app.lua
local lapis = require("lapis")
local app_helpers = require("lapis.application")
local validate = require("lapis.validate")
local cjson = require("cjson")
local capture_errors = app_helpers.capture_errors
local app = lapis.Application()
app:enable("etlua")
app.layout = false
validate.validate_functions.alphanumeric = function(input)
return string.match(input, "^[%w_%-]+$"), "must be alphanumeric"
end
-- たたいたコマンドのSTDOUTパージング
function app:parse_status(line)
local parts = {}
for word in line:gmatch("%S+") do table.insert(parts, word) end
local status = {
["name"] = parts[1],
["status"] = parts[2],
}
if status["status"] == 'RUNNING' then
status["pid"] = string.gsub(parts[4], ",", "")
status["uptime"] = parts[#parts]
elseif status["status"] == 'STOPPED' then
status["uptime"] = string.format("%s %s %s", parts[3], parts[4], parts[5])
end
return status
end
-- トップページにstatusの結果をテーブルで表示したいので、結果をselfにいれるとテンプレートで使えるようになる
app:get("/", function(self)
local handle = io.popen("/usr/bin/supervisorctl status" .. " 2>&1")
self.supervisor_status = {}
for line in handle:lines() do
table.insert(
self.supervisor_status,
self.app:parse_status(line)
)
end
handle:close()
return { render = 'index' }
end)
-- 最低限のvalidationとリスタートをかける処理
app:post("/:app_name/restart/", capture_errors(function(self)
validate.assert_valid(self.params, {
{ "app_name", exists = true, alphanumeric = true }
})
local app_name = self.params.app_name
local handle = io.popen("/usr/bin/supervisorctl restart " .. app_name .. " 2>&1")
self.message = {}
for line in handle:lines() do
table.insert(self.message, line)
end
return cjson.encode(self.message)
end))
return app
.
出来上がったものはこんな感じ: