update readme

master
codeskyblue 8 years ago
parent 48febc2a5d
commit 5d2e04fcb8

@ -1,5 +1,5 @@
language: go
go:
- 1.5
script:
- go get -v .
- 1.6
- 1.7
script: go test -v

@ -1,86 +1,53 @@
# gosuv
[![Build Status](https://travis-ci.org/codeskyblue/gosuv.svg)](https://travis-ci.org/codeskyblue/gosuv)
golang port of python-supervisor
## Program not implement
**Not done yet.**
God damn, maybe need to delete all the code and start from scrach again.
So need redesign, bye the old code
```
GET /api/procs
GET /api/procs/:name
PUT /api/procs/:name
- action: <restart|start|stop>
POST /api/procs
DELETE /api/procs/:name
```
golang port of python-supervisor
Features
* [ ] Log view
* [ ] Realtime log view
* [ ] Github webhook
## TODO
* web control page
* cli remove (DONE)
* [ ] Web control page
## Requirements
Go version at least `1.5+`
## Install
go get -v github.com/codeskyblue/gosuv
## Installation
```sh
go get -v github.com/codeskyblue/gosuv
```
## Usage
$ gosuv add --name timetest -- bash -c "while true; do date; sleep 1; done"
program "timetest" has been added.
$ gosuv status
NAME STATUS
timetest running
$ gosuv stop timetest
program "timetest" stopped
$ gosuv tail -n 2 timetest
line 1
line 2
line ...
$ gosuv remove timetest
# remove program which named timetest
# see more usage
$ gosuv help
# Config(TODO)
`~/.gosuv/config.yml` content example
```yaml
---
listen:
web: 0.0.0.0:9090
rpc: 127.0.0.1:54637
```sh
$ gosuv status
NAME STATUS
timetest running
$ gosuv help
...
```
All process save to `~/.gosuv/procs.yml`
## Configuration
Default config file stored in directory `$HOME/.gosuv/`
Web page will be look like just a table, have command `Start|Stop|Restart`, and got state
## Design
### Get or Update program
`<GET|PUT> /api/programs/:name`
# State
### Add new program
`POST /api/programs`
### Del program
`DELETE /api/programs/:name`
## State
Only 4 states. [ref](http://supervisord.org/subprocess.html#process-states)
![states](docs/states.png)
# Plugin Design
# Plugin Design (todo)
Current plugins:
- [tailf](https://github.com/codeskyblue/gosuv-tailf)
@ -97,60 +64,6 @@ There is a directory `showpid`
When run `gosuv showpid`, file `run` will be called.
# RPC Design
I decide to use [grpc](http://www.grpc.io/) in 2015-09-05
<https://github.com/grpc/grpc-go>
<https://github.com/golang/protobuf>
go get -u -v github.com/golang/protobuf/{proto,protoc-gen-go}
pbrpc/codegen.sh
**Need protoc 3.0** <http://www.cnblogs.com/yuhan-TB/p/4629362.html>
Do not use `brew install protobuf`, this will only install protoc 2.6
# Design
Has a folder `.gosuv` under `$HOME` path.
Here is the folder structure
$HOME/.gosuv
|-- gosuv.json
|-- logs/
|-- program1.log
|-- program2.log
For first run `gosuv` command, will run a golang server.
Server port default 17422 or from env defined `GOSUV_SERVER_PORT`.
When server get `TERM` signal, all processes spwaned by srever will be killed.
## How to add program to gosuv
Eg, current folder is in `/tmp/hello`
gosuv add --name "program1" -- ./program1 1888
Will add a record to `$HOME/.gosuv/programs.json`
{
"name": "program1",
"command": ["./program1", "1888"],
"directory": "/tmp/hello",
"environ": [],
}
Show status
$ gosuv status
program1 RUNNING
Stop program, ex: "program1"
$ gosuv stop program1
program1 stopped
## Use libs
* <https://github.com/ahmetalpbalkan/govvv>

@ -75,8 +75,8 @@
<button class="btn btn-default btn-xs" v-on:click="cmdStop(p.program.name)" :disabled="!canStop(p.status)">
<span class="glyphicon glyphicon-stop"></span> Stop
</button>
<button class="btn btn-default btn-xs" disabled="true">
<span class="glyphicon glyphicon-minus"></span> Tailf
<button class="btn btn-default btn-xs" v-on:click="cmdTail(p.program.name)">
<span class="glyphicon glyphicon-text-size"></span> Tailf
</button>
<button class="btn btn-default btn-xs" disabled="true">
<span class="glyphicon glyphicon-cog"></span> Setting

@ -12,6 +12,25 @@ function getQueryString(name) {
return null;
}
function newWebsocket(pathname, opts) {
var ws = new WebSocket(wsProtocol + "://" + location.host + pathname);
opts = opts || {};
ws.onopen = opts.onopen || function(evt) {
console.log("WS OPEN", pathname);
}
ws.onclose = opts.onclose || function(evt) {
console.log("CLOSE");
ws = null;
}
ws.onmessage = opts.onmessage || function(evt) {
console.log("response:" + evt.data);
}
ws.onerror = function(evt) {
console.error("error:", evt.data);
}
return ws;
}
var wsProtocol = location.protocol == "https:" ? "wss" : "ws";
var W = {};
@ -78,7 +97,7 @@ var vm = new Vue({
});
},
test: function() {
ws.send("Test");
console.log("test");
},
cmdStart: function(name) {
console.log(name);
@ -99,13 +118,40 @@ var vm = new Vue({
}
})
},
cmdTail: function(name) {
var that = this;
if (W.wsLog) {
W.wsLog.close()
}
W.wsLog = newWebsocket("/ws/logs/" + name, {
onopen: function(evt) {
that.log.content = "";
},
onmessage: function(evt) {
that.log.content += evt.data;
that.log.line_count = $.trim(that.log.content).split(/\r\n|\r|\n/).length;
if (that.log.follow) {
var pre = $(".realtime-log")[0];
setTimeout(function() {
pre.scrollTop = pre.scrollHeight - pre.clientHeight;
}, 1);
}
}
});
$("#modalTailf").modal({
show: true,
keyboard: true,
// keyboard: false,
// backdrop: 'static',
})
},
canStop: function(status) {
switch (status) {
case "running":
case "retry wait":
return true;
}
}
},
}
})
@ -151,25 +197,6 @@ $(function() {
});
function newWebsocket(pathname, opts) {
var ws = new WebSocket(wsProtocol + "://" + location.host + pathname);
opts = opts || {};
ws.onopen = opts.onopen || function(evt) {
console.log("WS OPEN", pathname);
}
ws.onclose = opts.onclose || function(evt) {
console.log("CLOSE");
ws = null;
}
ws.onmessage = opts.onmessage || function(evt) {
console.log("response:" + evt.data);
}
ws.onerror = function(evt) {
console.error("error:", evt.data);
}
return ws;
}
console.log("HEE")
function newEventWatcher() {
@ -207,20 +234,22 @@ $(function() {
}
})
W.wsLog = newWebsocket("/ws/logs/hee", {
onopen: function(evt) {
vm.log.content = "";
},
onmessage: function(evt) {
vm.log.content += evt.data;
vm.log.line_count = $.trim(vm.log.content).split(/\r\n|\r|\n/).length;
if (vm.log.follow) {
var pre = $(".realtime-log")[0];
setTimeout(function() {
pre.scrollTop = pre.scrollHeight - pre.clientHeight;
}, 1);
function newLogTail(name) {
W.wsLog = newWebsocket("/ws/logs/" + name, {
onopen: function(evt) {
vm.log.content = "";
},
onmessage: function(evt) {
vm.log.content += evt.data;
vm.log.line_count = $.trim(vm.log.content).split(/\r\n|\r|\n/).length;
if (vm.log.follow) {
var pre = $(".realtime-log")[0];
setTimeout(function() {
pre.scrollTop = pre.scrollHeight - pre.clientHeight;
}, 1);
}
}
}
})
})
}
});

Loading…
Cancel
Save