mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat: read nginx log
This commit is contained in:
parent
376b0535f0
commit
6e3004b0bc
10 changed files with 260 additions and 11 deletions
|
@ -5,3 +5,7 @@ JwtSecret =
|
||||||
Email =
|
Email =
|
||||||
HTTPChallengePort = 9180
|
HTTPChallengePort = 9180
|
||||||
StartCmd = login
|
StartCmd = login
|
||||||
|
|
||||||
|
[nginx_log]
|
||||||
|
AccessLogPath = /var/log/nginx/access.log
|
||||||
|
ErrorLogPath = /var/log/nginx/error.log
|
||||||
|
|
|
@ -8,7 +8,8 @@ import {
|
||||||
FileOutlined,
|
FileOutlined,
|
||||||
HomeOutlined,
|
HomeOutlined,
|
||||||
InfoCircleOutlined,
|
InfoCircleOutlined,
|
||||||
UserOutlined
|
UserOutlined,
|
||||||
|
FileTextOutlined
|
||||||
} from '@ant-design/icons-vue'
|
} from '@ant-design/icons-vue'
|
||||||
|
|
||||||
const {$gettext} = gettext
|
const {$gettext} = gettext
|
||||||
|
@ -87,6 +88,14 @@ export const routes = [
|
||||||
icon: CodeOutlined
|
icon: CodeOutlined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'nginx_log',
|
||||||
|
name: () => $gettext('Nginx Log'),
|
||||||
|
component: () => import('@/views/nginx_log/NginxLog.vue'),
|
||||||
|
meta: {
|
||||||
|
icon: FileTextOutlined
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'about',
|
path: 'about',
|
||||||
name: () => $gettext('About'),
|
name: () => $gettext('About'),
|
||||||
|
|
|
@ -20,7 +20,6 @@ const name = ref(route.params.name)
|
||||||
function change_tls(r: any) {
|
function change_tls(r: any) {
|
||||||
if (r) {
|
if (r) {
|
||||||
// deep copy servers[0] to servers[1]
|
// deep copy servers[0] to servers[1]
|
||||||
console.log(props.ngx_config)
|
|
||||||
const server = JSON.parse(JSON.stringify(props.ngx_config.servers[0]))
|
const server = JSON.parse(JSON.stringify(props.ngx_config.servers[0]))
|
||||||
|
|
||||||
props.ngx_config.servers.push(server)
|
props.ngx_config.servers.push(server)
|
||||||
|
|
93
frontend/src/views/nginx_log/NginxLog.vue
Normal file
93
frontend/src/views/nginx_log/NginxLog.vue
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {useGettext} from 'vue3-gettext'
|
||||||
|
import ws from '@/lib/websocket'
|
||||||
|
import {nextTick, onMounted, reactive, ref, watch} from 'vue'
|
||||||
|
import ReconnectingWebSocket from 'reconnecting-websocket'
|
||||||
|
|
||||||
|
const {$gettext} = useGettext()
|
||||||
|
|
||||||
|
const logContainer = ref(null)
|
||||||
|
|
||||||
|
let websocket: ReconnectingWebSocket | WebSocket
|
||||||
|
|
||||||
|
const control = reactive({
|
||||||
|
fetch: 'new'
|
||||||
|
})
|
||||||
|
|
||||||
|
function openWs() {
|
||||||
|
websocket = ws('/api/nginx_log')
|
||||||
|
websocket.send(JSON.stringify(control))
|
||||||
|
websocket.onopen = () => {
|
||||||
|
(logContainer.value as any as Element).innerHTML = ''
|
||||||
|
}
|
||||||
|
websocket.onmessage = (m: any) => {
|
||||||
|
const para = document.createElement('p')
|
||||||
|
para.appendChild(document.createTextNode(m.data.trim()));
|
||||||
|
|
||||||
|
(logContainer.value as any as Node).appendChild(para);
|
||||||
|
|
||||||
|
(logContainer.value as any as Element).scroll({
|
||||||
|
top: (logContainer.value as any as Element).scrollHeight,
|
||||||
|
left: 0,
|
||||||
|
behavior: 'smooth'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
openWs()
|
||||||
|
})
|
||||||
|
|
||||||
|
const auto_refresh = ref(true)
|
||||||
|
|
||||||
|
watch(auto_refresh, (value) => {
|
||||||
|
if (value) {
|
||||||
|
openWs()
|
||||||
|
} else {
|
||||||
|
websocket.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(control, () => {
|
||||||
|
(logContainer.value as any as Element).innerHTML = ''
|
||||||
|
auto_refresh.value = true
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
websocket.send(JSON.stringify(control))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-card :title="$gettext('Nginx Log')" :bordered="false">
|
||||||
|
<a-form layout="vertical">
|
||||||
|
<a-form-item :label="$gettext('Auto Refresh')">
|
||||||
|
<a-switch v-model:checked="auto_refresh"/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$gettext('Fetch')">
|
||||||
|
<a-select v-model:value="control.fetch" style="max-width: 200px">
|
||||||
|
<a-select-option value="all">All logs</a-select-option>
|
||||||
|
<a-select-option value="new">New logs</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
|
||||||
|
<a-card>
|
||||||
|
<pre class="nginx-log-container" ref="logContainer"></pre>
|
||||||
|
</a-card>
|
||||||
|
</a-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.nginx-log-container {
|
||||||
|
height: 60vh;
|
||||||
|
overflow: scroll;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
3
go.mod
3
go.mod
|
@ -32,6 +32,7 @@ require (
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||||
github.com/golang/protobuf v1.3.4 // indirect
|
github.com/golang/protobuf v1.3.4 // indirect
|
||||||
|
github.com/hpcloud/tail v1.0.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.2 // indirect
|
github.com/jinzhu/now v1.1.2 // indirect
|
||||||
github.com/json-iterator/go v1.1.9 // indirect
|
github.com/json-iterator/go v1.1.9 // indirect
|
||||||
|
@ -49,6 +50,8 @@ require (
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||||
golang.org/x/text v0.3.4 // indirect
|
golang.org/x/text v0.3.4 // indirect
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -227,6 +227,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
||||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||||
|
@ -692,6 +693,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
@ -704,6 +706,7 @@ gopkg.in/ns1/ns1-go.v2 v2.4.4/go.mod h1:GMnKY+ZuoJ+lVLL+78uSTjwTz2jMazq6AfGKQOYh
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -224,8 +224,8 @@ func DisableDomain(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete auto cert record
|
// delete auto cert record
|
||||||
cert := model.Cert{Domain: c.Param("name")}
|
certModel := model.Cert{Domain: c.Param("name")}
|
||||||
err = cert.Remove()
|
err = certModel.Remove()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
return
|
return
|
||||||
|
@ -265,8 +265,8 @@ func DeleteDomain(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cert := model.Cert{Domain: name}
|
certModel := model.Cert{Domain: name}
|
||||||
_ = cert.Remove()
|
_ = certModel.Remove()
|
||||||
|
|
||||||
err = os.Remove(availablePath)
|
err = os.Remove(availablePath)
|
||||||
|
|
||||||
|
@ -284,19 +284,19 @@ func DeleteDomain(c *gin.Context) {
|
||||||
func AddDomainToAutoCert(c *gin.Context) {
|
func AddDomainToAutoCert(c *gin.Context) {
|
||||||
domain := c.Param("domain")
|
domain := c.Param("domain")
|
||||||
|
|
||||||
cert, err := model.FirstOrCreateCert(domain)
|
certModel, err := model.FirstOrCreateCert(domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, cert)
|
c.JSON(http.StatusOK, certModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveDomainFromAutoCert(c *gin.Context) {
|
func RemoveDomainFromAutoCert(c *gin.Context) {
|
||||||
cert := model.Cert{
|
certModel := model.Cert{
|
||||||
Domain: c.Param("domain"),
|
Domain: c.Param("domain"),
|
||||||
}
|
}
|
||||||
err := cert.Remove()
|
err := certModel.Remove()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ErrHandler(c, err)
|
ErrHandler(c, err)
|
||||||
|
|
124
server/api/nginx_log.go
Normal file
124
server/api/nginx_log.go
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/hpcloud/tail"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type controlStruct struct {
|
||||||
|
Fetch string `json:"fetch"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func tailNginxLog(ws *websocket.Conn, controlChan chan controlStruct, errChan chan error) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
log.Println("tailNginxLog recovery", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var control controlStruct
|
||||||
|
|
||||||
|
for {
|
||||||
|
var seek tail.SeekInfo
|
||||||
|
if control.Fetch != "all" {
|
||||||
|
seek.Offset = 0
|
||||||
|
seek.Whence = io.SeekEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a tail
|
||||||
|
t, err := tail.TailFile(
|
||||||
|
settings.NginxLogSettings.AccessLogPath, tail.Config{Follow: true,
|
||||||
|
ReOpen: true, Location: &seek})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errChan <- errors.Wrap(err, "error NginxAccessLog Tail")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
var next = false
|
||||||
|
select {
|
||||||
|
case line := <-t.Lines:
|
||||||
|
// Print the text of each received line
|
||||||
|
err = ws.WriteMessage(websocket.TextMessage, []byte(line.Text))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
errChan <- errors.Wrap(err, "error NginxAccessLog write message")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case control = <-controlChan:
|
||||||
|
log.Println("control change")
|
||||||
|
next = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if next {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLogControl(ws *websocket.Conn, controlChan chan controlStruct, errChan chan error) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
log.Println("tailNginxLog recovery", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
msgType, payload, err := ws.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
errChan <- errors.Wrap(err, "error NginxAccessLog read message")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if msgType != websocket.TextMessage {
|
||||||
|
errChan <- errors.New("error NginxAccessLog message type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg controlStruct
|
||||||
|
err = json.Unmarshal(payload, &msg)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- errors.Wrap(err, "Error ReadWsAndWritePty json.Unmarshal")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controlChan <- msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NginxLog(c *gin.Context) {
|
||||||
|
var upGrader = websocket.Upgrader{
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// upgrade http to websocket
|
||||||
|
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("[Error] NginxAccessLog Upgrade", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer ws.Close()
|
||||||
|
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
controlChan := make(chan controlStruct, 1)
|
||||||
|
|
||||||
|
go tailNginxLog(ws, controlChan, errChan)
|
||||||
|
go handleLogControl(ws, controlChan, errChan)
|
||||||
|
|
||||||
|
if err = <-errChan; err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,6 +92,9 @@ func InitRouter() *gin.Engine {
|
||||||
|
|
||||||
// pty
|
// pty
|
||||||
g.GET("pty", api.Pty)
|
g.GET("pty", api.Pty)
|
||||||
|
|
||||||
|
// Nginx log
|
||||||
|
g.GET("nginx_log", api.NginxLog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@ type Server struct {
|
||||||
PageSize int
|
PageSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NginxLog struct {
|
||||||
|
AccessLogPath string
|
||||||
|
ErrorLogPath string
|
||||||
|
}
|
||||||
|
|
||||||
var ServerSettings = &Server{
|
var ServerSettings = &Server{
|
||||||
HttpPort: "9000",
|
HttpPort: "9000",
|
||||||
RunMode: "debug",
|
RunMode: "debug",
|
||||||
|
@ -38,10 +43,16 @@ var ServerSettings = &Server{
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var NginxLogSettings = &NginxLog{
|
||||||
|
AccessLogPath: "",
|
||||||
|
ErrorLogPath: "",
|
||||||
|
}
|
||||||
|
|
||||||
var ConfPath string
|
var ConfPath string
|
||||||
|
|
||||||
var sections = map[string]interface{}{
|
var sections = map[string]interface{}{
|
||||||
"server": ServerSettings,
|
"server": ServerSettings,
|
||||||
|
"nginx_log": NginxLogSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue