forked from x/ContextOS
mac pro tcp
This commit is contained in:
parent
5f7d55da1a
commit
15d4da1b18
@ -10,4 +10,5 @@ source etc/local.shy
|
|||||||
alias import nfs
|
alias import nfs
|
||||||
alias send send
|
alias send send
|
||||||
alias dial dial
|
alias dial dial
|
||||||
|
alias pwd pwd
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,13 @@
|
|||||||
package nfs // {{{
|
package nfs
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
import (
|
||||||
|
"bufio"
|
||||||
"contexts"
|
"contexts"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/nsf/termbox-go"
|
|
||||||
"github.com/skip2/go-qrcode"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"bufio"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/nsf/termbox-go"
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -22,10 +20,6 @@ import ( // {{{
|
|||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
var FileNotExist = errors.New("file not exist")
|
|
||||||
|
|
||||||
type NFS struct {
|
type NFS struct {
|
||||||
in *os.File
|
in *os.File
|
||||||
out *os.File
|
out *os.File
|
||||||
@ -35,7 +29,7 @@ type NFS struct {
|
|||||||
height int
|
height int
|
||||||
|
|
||||||
paths []string
|
paths []string
|
||||||
io net.Conn
|
io io.ReadWriter
|
||||||
|
|
||||||
send chan *ctx.Message
|
send chan *ctx.Message
|
||||||
recv chan *ctx.Message
|
recv chan *ctx.Message
|
||||||
@ -50,7 +44,7 @@ type NFS struct {
|
|||||||
*ctx.Context
|
*ctx.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nfs *NFS) open(name string) (*os.File, error) { // {{{
|
func (nfs *NFS) open(name string) (*os.File, error) {
|
||||||
if path.IsAbs(name) {
|
if path.IsAbs(name) {
|
||||||
nfs.Message.Log("info", "open %s", name)
|
nfs.Message.Log("info", "open %s", name)
|
||||||
return os.Open(name)
|
return os.Open(name)
|
||||||
@ -64,9 +58,7 @@ func (nfs *NFS) open(name string) (*os.File, error) { // {{{
|
|||||||
nfs.Log("info", "open %s", name)
|
nfs.Log("info", "open %s", name)
|
||||||
return os.Open(name)
|
return os.Open(name)
|
||||||
}
|
}
|
||||||
|
func dir(m *ctx.Message, name string, level int, deep bool, fields []string) {
|
||||||
// }}}
|
|
||||||
func dir(m *ctx.Message, name string, level int, deep bool, fields []string) { // {{{
|
|
||||||
back, e := os.Getwd()
|
back, e := os.Getwd()
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
os.Chdir(name)
|
os.Chdir(name)
|
||||||
@ -155,9 +147,7 @@ func dir(m *ctx.Message, name string, level int, deep bool, fields []string) { /
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) insert(rest []rune, letters []rune) []rune {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) insert(rest []rune, letters []rune) []rune { // {{{
|
|
||||||
n := len(rest)
|
n := len(rest)
|
||||||
l := len(letters)
|
l := len(letters)
|
||||||
rest = append(rest, letters...)
|
rest = append(rest, letters...)
|
||||||
@ -169,18 +159,13 @@ func (nfs *NFS) insert(rest []rune, letters []rune) []rune { // {{{
|
|||||||
}
|
}
|
||||||
return rest
|
return rest
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) escape(form string, args ...interface{}) *NFS {
|
||||||
// }}}
|
|
||||||
|
|
||||||
func (nfs *NFS) escape(form string, args ...interface{}) *NFS { // {{{
|
|
||||||
if !nfs.Caps("windows") {
|
if !nfs.Caps("windows") {
|
||||||
fmt.Fprintf(nfs.out, "\033[%s", fmt.Sprintf(form, args...))
|
fmt.Fprintf(nfs.out, "\033[%s", fmt.Sprintf(form, args...))
|
||||||
}
|
}
|
||||||
return nfs
|
return nfs
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) color(str string, attr ...int) *NFS {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) color(str string, attr ...int) *NFS { // {{{
|
|
||||||
if !nfs.Confs("color") {
|
if !nfs.Confs("color") {
|
||||||
fmt.Fprint(nfs.out, str)
|
fmt.Fprint(nfs.out, str)
|
||||||
return nfs
|
return nfs
|
||||||
@ -205,9 +190,7 @@ func (nfs *NFS) color(str string, attr ...int) *NFS { // {{{
|
|||||||
nfs.escape("0m")
|
nfs.escape("0m")
|
||||||
return nfs
|
return nfs
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) print(str string) bool {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) print(str string) bool { // {{{
|
|
||||||
ls := strings.Split(str, "\n")
|
ls := strings.Split(str, "\n")
|
||||||
for i, l := range ls {
|
for i, l := range ls {
|
||||||
rest := ""
|
rest := ""
|
||||||
@ -237,8 +220,7 @@ func (nfs *NFS) print(str string) bool { // {{{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
func (nfs *NFS) prompt(arg ...string) string {
|
||||||
func (nfs *NFS) prompt(arg ...string) string { // {{{
|
|
||||||
ps := nfs.Option("prompt")
|
ps := nfs.Option("prompt")
|
||||||
if nfs.Caps("windows") {
|
if nfs.Caps("windows") {
|
||||||
nfs.color(ps)
|
nfs.color(ps)
|
||||||
@ -269,10 +251,7 @@ func (nfs *NFS) prompt(arg ...string) string { // {{{
|
|||||||
}
|
}
|
||||||
return ps
|
return ps
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) zone(buf []string, top, height int) (row, col int) {
|
||||||
// }}}
|
|
||||||
|
|
||||||
func (nfs *NFS) zone(buf []string, top, height int) (row, col int) { // {{{
|
|
||||||
row, col = len(buf)-1, 0
|
row, col = len(buf)-1, 0
|
||||||
for i := nfs.Capi("cursor_pos"); i > top-1; {
|
for i := nfs.Capi("cursor_pos"); i > top-1; {
|
||||||
if i -= len(buf[row]) / nfs.width; len(buf[row])%nfs.width > 0 {
|
if i -= len(buf[row]) / nfs.width; len(buf[row])%nfs.width > 0 {
|
||||||
@ -286,9 +265,7 @@ func (nfs *NFS) zone(buf []string, top, height int) (row, col int) { // {{{
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) page(buf []string, row, col, top, height int, status bool) {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) page(buf []string, row, col, top, height int, status bool) { // {{{
|
|
||||||
nfs.escape("2J").escape("H")
|
nfs.escape("2J").escape("H")
|
||||||
begin := row
|
begin := row
|
||||||
|
|
||||||
@ -313,9 +290,7 @@ func (nfs *NFS) page(buf []string, row, col, top, height int, status bool) { //
|
|||||||
nfs.escape("E").color(fmt.Sprintf("pages: %d/%d", begin, len(nfs.pages)), nfs.Confi("statusfgcolor"), nfs.Confi("statusbgcolor"))
|
nfs.escape("E").color(fmt.Sprintf("pages: %d/%d", begin, len(nfs.pages)), nfs.Confi("statusfgcolor"), nfs.Confi("statusbgcolor"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) View(buf []string, top int, height int) {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) View(buf []string, top int, height int) { // {{{
|
|
||||||
|
|
||||||
row, col := nfs.zone(buf, top, height)
|
row, col := nfs.zone(buf, top, height)
|
||||||
nfs.page(buf, row, col, top, height, true)
|
nfs.page(buf, row, col, top, height, true)
|
||||||
@ -368,9 +343,7 @@ func (nfs *NFS) View(buf []string, top int, height int) { // {{{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) Read(p []byte) (n int, err error) {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) Read(p []byte) (n int, err error) { // {{{
|
|
||||||
if nfs.Caps("windows") || !nfs.Caps("termbox") {
|
if nfs.Caps("windows") || !nfs.Caps("termbox") {
|
||||||
return nfs.in.Read(p)
|
return nfs.in.Read(p)
|
||||||
}
|
}
|
||||||
@ -562,9 +535,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { // {{{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
||||||
|
|
||||||
func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
|
|
||||||
if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") {
|
if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") {
|
||||||
c.Caches = map[string]*ctx.Cache{
|
c.Caches = map[string]*ctx.Cache{
|
||||||
"pos": &ctx.Cache{Name: "pos", Value: "0", Help: "pos"},
|
"pos": &ctx.Cache{Name: "pos", Value: "0", Help: "pos"},
|
||||||
@ -589,16 +560,12 @@ func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|
||||||
nfs.Message = m
|
nfs.Message = m
|
||||||
nfs.width, nfs.height = 1, 1
|
nfs.width, nfs.height = 1, 1
|
||||||
return nfs
|
return nfs
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
nfs.Message = m
|
nfs.Message = m
|
||||||
if len(arg) > 0 && arg[0] == "scan" {
|
if len(arg) > 0 && arg[0] == "scan" {
|
||||||
nfs.Caches["windows"] = &ctx.Cache{Name: "windows", Value: "false", Help: "termbox"}
|
nfs.Caches["windows"] = &ctx.Cache{Name: "windows", Value: "false", Help: "termbox"}
|
||||||
@ -702,7 +669,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
m.Cap("stream", m.Option("stream"))
|
m.Cap("stream", m.Option("stream"))
|
||||||
nfs.io = m.Optionv("io").(net.Conn)
|
nfs.io = m.Optionv("io").(io.ReadWriter)
|
||||||
nfs.hand = map[int]*ctx.Message{}
|
nfs.hand = map[int]*ctx.Message{}
|
||||||
nfs.send = make(chan *ctx.Message, 10)
|
nfs.send = make(chan *ctx.Message, 10)
|
||||||
nfs.recv = make(chan *ctx.Message, 10)
|
nfs.recv = make(chan *ctx.Message, 10)
|
||||||
@ -744,10 +711,11 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() { //接收消息队列
|
go func() { //接收消息队列
|
||||||
bio := bufio.NewScanner(nfs.io)
|
|
||||||
var e error
|
var e error
|
||||||
var msg *ctx.Message
|
var msg *ctx.Message
|
||||||
for head, body := "", ""; bio.Scan(); {
|
head, body := "", ""
|
||||||
|
|
||||||
|
for bio := bufio.NewScanner(nfs.io); bio.Scan(); {
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
msg = m.Sess("target")
|
msg = m.Sess("target")
|
||||||
}
|
}
|
||||||
@ -755,9 +723,9 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
msg.Meta = map[string][]string{}
|
msg.Meta = map[string][]string{}
|
||||||
}
|
}
|
||||||
line := bio.Text()
|
line := bio.Text()
|
||||||
|
m.Log("recv", "(%s) %s", head, line)
|
||||||
m.Capi("nread", len(line)+1)
|
m.Capi("nread", len(line)+1)
|
||||||
if len(line) == 0 {
|
if len(line) == 0 {
|
||||||
|
|
||||||
if head == "detail" {
|
if head == "detail" {
|
||||||
m.Log("info", "%d recv: %v %v %v", m.Capi("nrecv", 1), msg.Meta[head], msg.Meta[body], msg.Meta)
|
m.Log("info", "%d recv: %v %v %v", m.Capi("nrecv", 1), msg.Meta[head], msg.Meta[body], msg.Meta)
|
||||||
msg.Option("recv_code", m.Cap("nrecv"))
|
msg.Option("recv_code", m.Cap("nrecv"))
|
||||||
@ -768,7 +736,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
h.Copy(msg, "result").Copy(msg, "append")
|
h.Copy(msg, "result").Copy(msg, "append")
|
||||||
h.Remote <- true
|
h.Remote <- true
|
||||||
}
|
}
|
||||||
msg = nil
|
msg, head, body = nil, "", "append"
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,9 +767,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
return false
|
return false
|
||||||
switch nfs.Context {
|
switch nfs.Context {
|
||||||
case m.Target():
|
case m.Target():
|
||||||
@ -813,17 +779,12 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
nfs.out.Close()
|
nfs.out.Close()
|
||||||
nfs.out = nil
|
nfs.out = nil
|
||||||
}
|
}
|
||||||
if nfs.io != nil {
|
|
||||||
nfs.io.Close()
|
|
||||||
nfs.io = nil
|
|
||||||
}
|
|
||||||
case m.Source():
|
case m.Source():
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
var FileNotExist = errors.New("file not exist")
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
||||||
Caches: map[string]*ctx.Cache{
|
Caches: map[string]*ctx.Cache{
|
||||||
"nfile": &ctx.Cache{Name: "nfile", Value: "-1", Help: "已经打开的文件数量"},
|
"nfile": &ctx.Cache{Name: "nfile", Value: "-1", Help: "已经打开的文件数量"},
|
||||||
@ -831,11 +792,11 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
Configs: map[string]*ctx.Config{
|
Configs: map[string]*ctx.Config{
|
||||||
"pscolor": &ctx.Config{Name: "pscolor", Value: "2", Help: "pscolor"},
|
"pscolor": &ctx.Config{Name: "pscolor", Value: "2", Help: "pscolor"},
|
||||||
"nfs_name": &ctx.Config{Name: "nfs_name", Value: "file", Help: "默认模块命名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
|
"nfs_name": &ctx.Config{Name: "nfs_name", Value: "file", Help: "默认模块命名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
|
||||||
if len(arg) > 0 { // {{{
|
if len(arg) > 0 {
|
||||||
return arg[0]
|
return arg[0]
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s%d", x.Value, m.Capi("nfile", 1))
|
return fmt.Sprintf("%s%d", x.Value, m.Capi("nfile", 1))
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"nfs_help": &ctx.Config{Name: "nfs_help", Value: "file", Help: "默认模块帮助"},
|
"nfs_help": &ctx.Config{Name: "nfs_help", Value: "file", Help: "默认模块帮助"},
|
||||||
|
|
||||||
@ -865,7 +826,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
Name: "paths [add path]|[del index]|[set index path]|[index]",
|
Name: "paths [add path]|[del index]|[set index path]|[index]",
|
||||||
Help: "设置文件搜索路径, add: 添加目录, del: 删除目录, set: 修改目录,index: 目录序号, path: 目录名",
|
Help: "设置文件搜索路径, add: 添加目录, del: 删除目录, set: 修改目录,index: 目录序号, path: 目录名",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) { // {{{
|
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) {
|
||||||
if len(arg) == 0 {
|
if len(arg) == 0 {
|
||||||
for i, v := range nfs.paths {
|
for i, v := range nfs.paths {
|
||||||
m.Echo("%d: %s\n", i, v)
|
m.Echo("%d: %s\n", i, v)
|
||||||
@ -892,13 +853,13 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
m.Echo("%d: %s\n", i, nfs.paths[i])
|
m.Echo("%d: %s\n", i, nfs.paths[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"scan": &ctx.Command{
|
"scan": &ctx.Command{
|
||||||
Name: "scan filename [nfs_name [nfs_help]]",
|
Name: "scan filename [nfs_name [nfs_help]]",
|
||||||
Help: "扫描文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助",
|
Help: "扫描文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) { // {{{
|
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) {
|
||||||
if arg[0] == "stdio" {
|
if arg[0] == "stdio" {
|
||||||
m.Optionv("in", os.Stdin)
|
m.Optionv("in", os.Stdin)
|
||||||
m.Optionv("out", os.Stdout)
|
m.Optionv("out", os.Stdout)
|
||||||
@ -909,13 +870,13 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
}
|
}
|
||||||
|
|
||||||
m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), key, arg[0])
|
m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), key, arg[0])
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"history": &ctx.Command{
|
"history": &ctx.Command{
|
||||||
Name: "history [save|load filename [lines [pos]]] [find|search key]",
|
Name: "history [save|load filename [lines [pos]]] [find|search key]",
|
||||||
Help: "扫描记录, save: 保存记录, load: 加载记录, filename: 文件名, lines: 加载或保存记录数量, pos: 加载或保存的起始位置, find: 查找记录, search: 搜索记录, key: 查找或搜索的参数",
|
Help: "扫描记录, save: 保存记录, load: 加载记录, filename: 文件名, lines: 加载或保存记录数量, pos: 加载或保存的起始位置, find: 查找记录, search: 搜索记录, key: 查找或搜索的参数",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) { // {{{
|
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) {
|
||||||
if len(arg) == 0 {
|
if len(arg) == 0 {
|
||||||
for i, v := range nfs.history {
|
for i, v := range nfs.history {
|
||||||
m.Echo("%d: %s\n", i, v)
|
m.Echo("%d: %s\n", i, v)
|
||||||
@ -1000,34 +961,34 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
m.Echo(nfs.history[i])
|
m.Echo(nfs.history[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"open": &ctx.Command{
|
"open": &ctx.Command{
|
||||||
Name: "open filename [nfs_name [nfs_help]]",
|
Name: "open filename [nfs_name [nfs_help]]",
|
||||||
Help: "打开文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助",
|
Help: "打开文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if m.Has("io") { // {{{
|
if m.Has("io") {
|
||||||
} else if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE, os.ModePerm); m.Assert(e) {
|
} else if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE, os.ModePerm); m.Assert(e) {
|
||||||
m.Put("option", "in", f).Put("option", "out", f)
|
m.Put("option", "in", f).Put("option", "out", f)
|
||||||
}
|
}
|
||||||
m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), "open", arg[0])
|
m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), "open", arg[0])
|
||||||
m.Echo(m.Target().Name)
|
m.Echo(m.Target().Name)
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"append": &ctx.Command{
|
"append": &ctx.Command{
|
||||||
Name: "append filename [nfs_name [nfs_help]]",
|
Name: "append filename [nfs_name [nfs_help]]",
|
||||||
Help: "打开文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助",
|
Help: "打开文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if m.Has("io") { // {{{
|
if m.Has("io") {
|
||||||
} else if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm); m.Assert(e) {
|
} else if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm); m.Assert(e) {
|
||||||
m.Put("option", "in", f).Put("option", "out", f)
|
m.Put("option", "in", f).Put("option", "out", f)
|
||||||
}
|
}
|
||||||
m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), "append", arg[0])
|
m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), "append", arg[0])
|
||||||
m.Echo(m.Target().Name)
|
m.Echo(m.Target().Name)
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil { // {{{
|
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil {
|
||||||
n, e := strconv.Atoi(m.Confx("buf_size", arg, 0))
|
n, e := strconv.Atoi(m.Confx("buf_size", arg, 0))
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
|
||||||
@ -1045,10 +1006,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
if m.Capi("pos", n); n == 0 {
|
if m.Capi("pos", n); n == 0 {
|
||||||
m.Cap("pos", "0")
|
m.Cap("pos", "0")
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { // {{{
|
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil {
|
||||||
if len(arg) > 1 {
|
if len(arg) > 1 {
|
||||||
m.Cap("pos", arg[1])
|
m.Cap("pos", arg[1])
|
||||||
}
|
}
|
||||||
@ -1066,10 +1027,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
}
|
}
|
||||||
|
|
||||||
m.Echo(m.Cap("pos"))
|
m.Echo(m.Cap("pos"))
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if f, e := os.Open(arg[0]); m.Assert(e) { // {{{
|
if f, e := os.Open(arg[0]); m.Assert(e) {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
pos := 0
|
pos := 0
|
||||||
@ -1087,34 +1048,34 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
m.Log("info", "read %d", l)
|
m.Log("info", "read %d", l)
|
||||||
m.Echo(string(buf[:l]))
|
m.Echo(string(buf[:l]))
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"save": &ctx.Command{Name: "save file string...", Help: "保存文件, file: 保存的文件, string: 保存的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"save": &ctx.Command{Name: "save file string...", Help: "保存文件, file: 保存的文件, string: 保存的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if f, e := os.Create(arg[0]); m.Assert(e) { // {{{
|
if f, e := os.Create(arg[0]); m.Assert(e) {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
for _, v := range arg[1:] {
|
for _, v := range arg[1:] {
|
||||||
fmt.Fprint(f, v)
|
fmt.Fprint(f, v)
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"print": &ctx.Command{Name: "print file string...", Help: "输出文件, file: 输出的文件, string: 输出的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"print": &ctx.Command{Name: "print file string...", Help: "输出文件, file: 输出的文件, string: 输出的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if f, e := os.OpenFile(arg[0], os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); m.Assert(e) { // {{{
|
if f, e := os.OpenFile(arg[0], os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); m.Assert(e) {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
for _, v := range arg[1:] {
|
for _, v := range arg[1:] {
|
||||||
fmt.Fprint(f, v)
|
fmt.Fprint(f, v)
|
||||||
}
|
}
|
||||||
fmt.Fprint(f, "\n")
|
fmt.Fprint(f, "\n")
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"genqr": &ctx.Command{Name: "genqr [qr_size size] filename string...", Help: "生成二维码图片, qr_size: 图片大小, filename: 文件名, string: 输出内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"genqr": &ctx.Command{Name: "genqr [qr_size size] filename string...", Help: "生成二维码图片, qr_size: 图片大小, filename: 文件名, string: 输出内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if size, e := strconv.Atoi(m.Confx("qr_size")); m.Assert(e) { // {{{
|
if size, e := strconv.Atoi(m.Confx("qr_size")); m.Assert(e) {
|
||||||
qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, arg[0])
|
qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, arg[0])
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"json": &ctx.Command{Name: "json [key value]...", Help: "生成格式化内容, key: 参数名, value: 参数值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"json": &ctx.Command{Name: "json [key value]...", Help: "生成格式化内容, key: 参数名, value: 参数值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if len(arg) == 1 { // {{{
|
if len(arg) == 1 {
|
||||||
var data interface{}
|
var data interface{}
|
||||||
e := json.Unmarshal([]byte(arg[0]), &data)
|
e := json.Unmarshal([]byte(arg[0]), &data)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
@ -1156,10 +1117,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
buf, e := json.Marshal(data)
|
buf, e := json.Marshal(data)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
m.Echo(string(buf))
|
m.Echo(string(buf))
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"pwd": &ctx.Command{Name: "pwd", Help: "查看当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"pwd": &ctx.Command{Name: "pwd", Help: "查看当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if m.Options("dir") { // {{{
|
if m.Options("dir") {
|
||||||
m.Echo(m.Option("dir"))
|
m.Echo(m.Option("dir"))
|
||||||
m.Add("append", "hi", "hello")
|
m.Add("append", "hi", "hello")
|
||||||
m.Add("append", "he", "hello")
|
m.Add("append", "he", "hello")
|
||||||
@ -1172,7 +1133,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
}
|
}
|
||||||
wd, e := os.Getwd()
|
wd, e := os.Getwd()
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
m.Echo(wd) // }}}
|
m.Echo(wd)
|
||||||
m.Append("hi", "hello")
|
m.Append("hi", "hello")
|
||||||
}},
|
}},
|
||||||
"dir": &ctx.Command{
|
"dir": &ctx.Command{
|
||||||
@ -1180,7 +1141,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
Help: "查看目录, dir: 目录名, dir_info: 显示统计信息, dir_name: 文件名类型, dir_type: 文件类型, sort_field: 排序字段, sort_order: 排序类型",
|
Help: "查看目录, dir: 目录名, dir_info: 显示统计信息, dir_name: 文件名类型, dir_type: 文件类型, sort_field: 排序字段, sort_order: 排序类型",
|
||||||
Form: map[string]int{"dir_field": 1, "dir_deep": 1, "dir_info": 1, "dir_name": 1, "dir_type": 1, "sort_field": 1, "sort_order": 1},
|
Form: map[string]int{"dir_field": 1, "dir_deep": 1, "dir_info": 1, "dir_name": 1, "dir_type": 1, "sort_field": 1, "sort_order": 1},
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
d := "./" + m.Option("dir") // {{{
|
d := "./" + m.Option("dir")
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 {
|
||||||
d = arg[0]
|
d = arg[0]
|
||||||
}
|
}
|
||||||
@ -1224,14 +1185,14 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
for _, v := range info {
|
for _, v := range info {
|
||||||
m.Echo("%s: %s\n", v, m.Option(v))
|
m.Echo("%s: %s\n", v, m.Option(v))
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"git": &ctx.Command{
|
"git": &ctx.Command{
|
||||||
Name: "git branch|status|diff|log|info arg... [dir path]...",
|
Name: "git branch|status|diff|log|info arg... [dir path]...",
|
||||||
Help: "版本控制, branch: 分支管理, status: 查看状态, info: 查看分支与状态, dir: 指定路径",
|
Help: "版本控制, branch: 分支管理, status: 查看状态, info: 查看分支与状态, dir: 指定路径",
|
||||||
Form: map[string]int{"dir": 1, "git_info": 1, "git_log": 1, "git_log_form": 1},
|
Form: map[string]int{"dir": 1, "git_info": 1, "git_log": 1, "git_log_form": 1},
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if len(arg) == 0 { // {{{
|
if len(arg) == 0 {
|
||||||
arg = []string{"info"}
|
arg = []string{"info"}
|
||||||
}
|
}
|
||||||
cmds := []string{arg[0]}
|
cmds := []string{arg[0]}
|
||||||
@ -1354,7 +1315,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
m.Copy(msg, "result").Copy(msg, "append")
|
m.Copy(msg, "result").Copy(msg, "append")
|
||||||
m.Echo("\n")
|
m.Echo("\n")
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
|
|
||||||
"listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
@ -1370,7 +1331,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
})
|
})
|
||||||
}, m.Meta["detail"])
|
}, m.Meta["detail"])
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"dial": &ctx.Command{Name: "dial args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"dial": &ctx.Command{Name: "dial args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{
|
if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{
|
||||||
@ -1385,14 +1346,14 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
|
|||||||
})
|
})
|
||||||
}, m.Meta["detail"])
|
}, m.Meta["detail"])
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"send": &ctx.Command{Name: "send [file] args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"send": &ctx.Command{Name: "send [file] args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.io != nil { // {{{
|
if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.io != nil {
|
||||||
m.Remote = make(chan bool, 1)
|
m.Remote = make(chan bool, 1)
|
||||||
nfs.send <- m
|
nfs.send <- m
|
||||||
<-m.Remote
|
<-m.Remote
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
package ssh // {{{
|
package ssh
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
|
||||||
"contexts"
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"contexts"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
type SSH struct {
|
type SSH struct {
|
||||||
nfs *ctx.Context
|
nfs *ctx.Context
|
||||||
peer map[string]*ctx.Message
|
peer map[string]*ctx.Message
|
||||||
@ -17,35 +14,27 @@ type SSH struct {
|
|||||||
*ctx.Context
|
*ctx.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ssh *SSH) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
|
func (ssh *SSH) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
||||||
c.Caches = map[string]*ctx.Cache{
|
c.Caches = map[string]*ctx.Cache{}
|
||||||
"hostname": &ctx.Cache{Name: "hostname", Value: "com", Help: "主机数量"},
|
|
||||||
}
|
|
||||||
c.Configs = map[string]*ctx.Config{}
|
c.Configs = map[string]*ctx.Config{}
|
||||||
|
|
||||||
s := new(SSH)
|
s := new(SSH)
|
||||||
s.Context = c
|
s.Context = c
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (ssh *SSH) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||||
// }}}
|
|
||||||
func (ssh *SSH) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|
||||||
ssh.Caches["hostname"] = &ctx.Cache{Name: "hostname", Value: "", Help: "主机数量"}
|
ssh.Caches["hostname"] = &ctx.Cache{Name: "hostname", Value: "", Help: "主机数量"}
|
||||||
if ssh.Context == Index {
|
if ssh.Context == Index {
|
||||||
Pulse = m
|
Pulse = m
|
||||||
}
|
}
|
||||||
return ssh
|
return ssh
|
||||||
}
|
}
|
||||||
|
func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
ssh.nfs = m.Source()
|
ssh.nfs = m.Source()
|
||||||
m.Cap("stream", m.Source().Name)
|
m.Cap("stream", m.Source().Name)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
return false
|
return false
|
||||||
switch ssh.Context {
|
switch ssh.Context {
|
||||||
case m.Target():
|
case m.Target():
|
||||||
@ -65,19 +54,14 @@ func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
func Done(m *ctx.Message, lock chan bool) {
|
||||||
// }}}
|
|
||||||
|
|
||||||
func Done(m *ctx.Message, lock chan bool) { // {{{
|
|
||||||
m.Log("lock", "done before %v", m.Meta["detail"])
|
m.Log("lock", "done before %v", m.Meta["detail"])
|
||||||
if m.Options("stdio") {
|
if m.Options("stdio") {
|
||||||
lock <- true
|
lock <- true
|
||||||
}
|
}
|
||||||
m.Log("lock", "done after %v", m.Meta["detail"])
|
m.Log("lock", "done after %v", m.Meta["detail"])
|
||||||
}
|
}
|
||||||
|
func Wait(m *ctx.Message, lock chan bool) {
|
||||||
// }}}
|
|
||||||
func Wait(m *ctx.Message, lock chan bool) { // {{{
|
|
||||||
m.Log("lock", "wait before %v", m.Meta["detail"])
|
m.Log("lock", "wait before %v", m.Meta["detail"])
|
||||||
if m.Options("stdio") {
|
if m.Options("stdio") {
|
||||||
<-lock
|
<-lock
|
||||||
@ -85,22 +69,21 @@ func Wait(m *ctx.Message, lock chan bool) { // {{{
|
|||||||
m.Log("lock", "wait after %v", m.Meta["detail"])
|
m.Log("lock", "wait after %v", m.Meta["detail"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
var Pulse *ctx.Message
|
var Pulse *ctx.Message
|
||||||
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
||||||
Caches: map[string]*ctx.Cache{
|
Caches: map[string]*ctx.Cache{
|
||||||
"nhost": &ctx.Cache{Name: "主机数量", Value: "0", Help: "主机数量"},
|
"nhost": &ctx.Cache{Name: "主机数量", Value: "0", Help: "主机数量"},
|
||||||
|
"domain": &ctx.Cache{Name: "domain", Value: "", Help: "主机域名"},
|
||||||
|
|
||||||
"route": &ctx.Cache{Name: "route", Value: "com", Help: "主机数量"},
|
"route": &ctx.Cache{Name: "route", Value: "com", Help: "主机数量"},
|
||||||
"count": &ctx.Cache{Name: "count", Value: "3", Help: "主机数量"},
|
"count": &ctx.Cache{Name: "count", Value: "3", Help: "主机数量"},
|
||||||
"share": &ctx.Cache{Name: "share", Value: "root", Help: "主机数量"},
|
"share": &ctx.Cache{Name: "share", Value: "root", Help: "主机数量"},
|
||||||
"level": &ctx.Cache{Name: "level", Value: "root", Help: "主机数量"},
|
"level": &ctx.Cache{Name: "level", Value: "root", Help: "主机数量"},
|
||||||
|
|
||||||
"domain": &ctx.Cache{Name: "domain", Value: "com", Help: "主机数量"},
|
|
||||||
},
|
},
|
||||||
Configs: map[string]*ctx.Config{
|
Configs: map[string]*ctx.Config{
|
||||||
|
"hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机数量"},
|
||||||
|
|
||||||
"interval": &ctx.Config{Name: "interval", Value: "3", Help: "主机数量"},
|
"interval": &ctx.Config{Name: "interval", Value: "3", Help: "主机数量"},
|
||||||
"hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机数量"},
|
|
||||||
"domain.json": &ctx.Config{Name: "domain.json", Value: "var/domain.json", Help: "主机数量"},
|
"domain.json": &ctx.Config{Name: "domain.json", Value: "var/domain.json", Help: "主机数量"},
|
||||||
"domain.png": &ctx.Config{Name: "domain.png", Value: "var/domain.png", Help: "主机数量"},
|
"domain.png": &ctx.Config{Name: "domain.png", Value: "var/domain.png", Help: "主机数量"},
|
||||||
|
|
||||||
@ -113,35 +96,48 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|||||||
"mark": &ctx.Config{Name: "mark", Value: "com", Help: "主机数量"},
|
"mark": &ctx.Config{Name: "mark", Value: "com", Help: "主机数量"},
|
||||||
},
|
},
|
||||||
Commands: map[string]*ctx.Command{
|
Commands: map[string]*ctx.Command{
|
||||||
"listen": &ctx.Command{Name: "listen address protocol", Help: "监听连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) {
|
||||||
m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message {
|
m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message {
|
||||||
sub.Start(fmt.Sprintf("host%d", Pulse.Capi("nhost", 1)), "远程主机")
|
sub.Start(fmt.Sprintf("host%d", Pulse.Capi("nhost", 1)), "远程主机")
|
||||||
|
// sub.Spawn().Cmd("pwd", "init")
|
||||||
return sub
|
return sub
|
||||||
}, m.Meta["detail"])
|
}, m.Meta["detail"])
|
||||||
m.Spawn(m.Target()).Cmd("save")
|
if !m.Caps("domain") {
|
||||||
|
m.Cap("domain", m.Cap("hostname", m.Conf("hostname")))
|
||||||
|
}
|
||||||
|
// m.Spawn(m.Target()).Cmd("save")
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"dial": &ctx.Command{Name: "dial address protocol", Help: "建立连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) {
|
||||||
m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message {
|
m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message {
|
||||||
sub.Target().Start(sub)
|
sub.Target().Start(sub)
|
||||||
sub.Spawn().Cmd("pwd", m.Conf("hostname"))
|
|
||||||
return sub
|
return sub
|
||||||
}, m.Meta["detail"])
|
}, m.Meta["detail"])
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行",
|
"send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) {
|
||||||
domain := ""
|
domain := ""
|
||||||
if len(arg) > 1 && arg[0] == "domain" {
|
if len(arg) > 1 && arg[0] == "domain" {
|
||||||
domain, arg = arg[1], arg[2:]
|
domain, arg = arg[1], arg[2:]
|
||||||
domain = strings.TrimPrefix(strings.TrimPrefix(domain, m.Cap("domain")), ".")
|
domain = strings.TrimPrefix(strings.TrimPrefix(domain, m.Cap("domain")), ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.Has("send_code") {
|
||||||
|
msg := m.Spawn().Cmd(arg)
|
||||||
|
m.Copy(msg, "result").Copy(msg, "append")
|
||||||
|
} else {
|
||||||
|
msg := m.Spawn(ssh.Message().Source())
|
||||||
|
msg.Cmd("send", arg)
|
||||||
|
m.Copy(msg, "result").Copy(msg, "append")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
if domain != "" {
|
if domain != "" {
|
||||||
domain_miss := true
|
domain_miss := true
|
||||||
host := strings.SplitN(domain, ".", 2)
|
host := strings.SplitN(domain, ".", 2)
|
||||||
@ -197,36 +193,45 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|||||||
m.Copy(msg, "result").Copy(msg, "append")
|
m.Copy(msg, "result").Copy(msg, "append")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if len(arg) == 0 { // {{{
|
if len(arg) > 0 {
|
||||||
if m.Target() == c {
|
if m.Options("send_code") {
|
||||||
m.Echo(m.Cap("domain"))
|
if m.Target() == c {
|
||||||
} else {
|
msg := m.Spawn().Cmd("send", "pwd", m.Confx("hostname", arg, 0))
|
||||||
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname"))
|
m.Cap("hostname", msg.Result(0))
|
||||||
|
m.Cap("domain", msg.Result(1))
|
||||||
|
} else {
|
||||||
|
hostname := arg[0]
|
||||||
|
m.Travel(func(m *ctx.Message, line int) bool {
|
||||||
|
if hostname == m.Cap("hostname") {
|
||||||
|
hostname += m.Cap("nhost")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}, c)
|
||||||
|
m.Echo(m.Cap("hostname", hostname))
|
||||||
|
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname"))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.Target() == c {
|
||||||
|
m.Conf("hostname", arg[0])
|
||||||
|
msg := m.Spawn().Cmd("send", "pwd", arg[0])
|
||||||
|
m.Cap("hostname", msg.Result(0))
|
||||||
|
m.Cap("domain", msg.Result(1))
|
||||||
|
} else {
|
||||||
|
m.Spawn().Cmd("send", "pwd", arg[0])
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Target() == c {
|
m.Echo(m.Cap("domain"))
|
||||||
msg := m.Spawn().Cmd("send", "pwd", arg[0])
|
|
||||||
m.Copy(msg, "result").Copy(msg, "append")
|
|
||||||
m.Cap("domain", msg.Result(0))
|
|
||||||
} else if m.Options("send_code") {
|
|
||||||
hostname := arg[0]
|
|
||||||
m.Travel(func(m *ctx.Message, line int) bool {
|
|
||||||
if hostname == m.Cap("hostname") {
|
|
||||||
hostname += m.Cap("nhost")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}, c)
|
|
||||||
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname", hostname))
|
|
||||||
} // }}}
|
|
||||||
}},
|
}},
|
||||||
"hello": &ctx.Command{Name: "hello request", Help: "加密请求", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"hello": &ctx.Command{Name: "hello request", Help: "加密请求", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
aaa := m.Target().Message().Sess("aaa", false) // {{{
|
aaa := m.Target().Message().Sess("aaa", false)
|
||||||
for _, k := range m.Meta["seal"] {
|
for _, k := range m.Meta["seal"] {
|
||||||
for i, v := range m.Meta[k] {
|
for i, v := range m.Meta[k] {
|
||||||
m.Meta[k][i] = m.Spawn(aaa).Cmd("deal", v).Result(0)
|
m.Meta[k][i] = m.Spawn(aaa).Cmd("deal", v).Result(0)
|
||||||
@ -252,14 +257,14 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|||||||
|
|
||||||
msg := m.Spawn().Copy(m, "option").Cmd(arg)
|
msg := m.Spawn().Copy(m, "option").Cmd(arg)
|
||||||
m.Copy(msg, "result").Copy(msg, "append")
|
m.Copy(msg, "result").Copy(msg, "append")
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"shake": &ctx.Command{
|
"shake": &ctx.Command{
|
||||||
Name: "shake [domain host] cmd... [seal option...][encrypt option...]",
|
Name: "shake [domain host] cmd... [seal option...][encrypt option...]",
|
||||||
Help: "加密通信",
|
Help: "加密通信",
|
||||||
Form: map[string]int{"seal": -1, "encrypt": -1},
|
Form: map[string]int{"seal": -1, "encrypt": -1},
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
|
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) {
|
||||||
if len(arg) == 0 {
|
if len(arg) == 0 {
|
||||||
for k, v := range ssh.peer {
|
for k, v := range ssh.peer {
|
||||||
m.Echo("%s: %s\n", k, v.Cap("stream"))
|
m.Echo("%s: %s\n", k, v.Cap("stream"))
|
||||||
@ -304,7 +309,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|||||||
msg.Detail("send", args, "hello", arg)
|
msg.Detail("send", args, "hello", arg)
|
||||||
ssh.Message().Back(msg)
|
ssh.Message().Back(msg)
|
||||||
m.Copy(msg, "result").Copy(msg, "append")
|
m.Copy(msg, "result").Copy(msg, "append")
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"close": &ctx.Command{Name: "close", Help: "连接断开", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"close": &ctx.Command{Name: "close", Help: "连接断开", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
m.Target().Close(m)
|
m.Target().Close(m)
|
||||||
@ -319,21 +324,21 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|||||||
}, c)
|
}, c)
|
||||||
}},
|
}},
|
||||||
"save": &ctx.Command{Name: "save", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"save": &ctx.Command{Name: "save", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
json := m.Sess("nfs") // {{{
|
json := m.Sess("nfs")
|
||||||
json.Put("option", "data", map[string]string{"domain": m.Cap("domain")})
|
json.Put("option", "data", map[string]string{"domain": m.Cap("domain")})
|
||||||
json.Cmd("json", m.Conf("domain.json"))
|
json.Cmd("json", m.Conf("domain.json"))
|
||||||
m.Sess("nfs").Cmd("genqr", m.Conf("domain.png"), json.Result(0))
|
m.Sess("nfs").Cmd("genqr", m.Conf("domain.png"), json.Result(0))
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"who": &ctx.Command{Name: "who", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"who": &ctx.Command{Name: "who", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
aaa := m.Sess("aaa") // {{{
|
aaa := m.Sess("aaa")
|
||||||
if aaa != nil {
|
if aaa != nil {
|
||||||
m.Echo(aaa.Cap("group"))
|
m.Echo(aaa.Cap("group"))
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"good": &ctx.Command{Name: "good context|command|config|cache args", Help: "设备注册", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) {
|
"good": &ctx.Command{Name: "good context|command|config|cache args", Help: "设备注册", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) {
|
||||||
if len(arg) == 0 { // {{{
|
if len(arg) == 0 {
|
||||||
m.Append("share", m.Cap("share"))
|
m.Append("share", m.Cap("share"))
|
||||||
m.Append("level", m.Cap("level"))
|
m.Append("level", m.Cap("level"))
|
||||||
m.Append("type", m.Conf("type"))
|
m.Append("type", m.Conf("type"))
|
||||||
@ -399,7 +404,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
|
|||||||
m.Add("append", "value", x.Value)
|
m.Add("append", "value", x.Value)
|
||||||
m.Add("append", "help", x.Help)
|
m.Add("append", "help", x.Help)
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package tcp // {{{
|
package tcp
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
|
||||||
"contexts"
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"contexts"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -10,22 +9,36 @@ import ( // {{{
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
type TCP struct {
|
type TCP struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
net.Listener
|
net.Listener
|
||||||
*ctx.Context
|
*ctx.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcp *TCP) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
|
func (tcp *TCP) Read(b []byte) (n int, e error) {
|
||||||
|
m := tcp.Context.Message()
|
||||||
|
m.Assert(tcp.Conn != nil)
|
||||||
|
n, e = tcp.Conn.Read(b)
|
||||||
|
m.Capi("nrecv", n)
|
||||||
|
m.Assert(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (tcp *TCP) Write(b []byte) (n int, e error) {
|
||||||
|
m := tcp.Context.Message()
|
||||||
|
m.Assert(tcp.Conn != nil)
|
||||||
|
n, e = tcp.Conn.Write(b)
|
||||||
|
m.Capi("nsend", n)
|
||||||
|
m.Assert(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tcp *TCP) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
||||||
c.Caches = map[string]*ctx.Cache{
|
c.Caches = map[string]*ctx.Cache{
|
||||||
"protocol": &ctx.Cache{Name: "网络协议(tcp/tcp4/tcp6)", Value: m.Conf("protocol"), Help: "网络协议"},
|
"protocol": &ctx.Cache{Name: "protocol(tcp/tcp4/tcp6)", Value: "", Help: "网络协议"},
|
||||||
"certfile": &ctx.Cache{Name: "certfile", Value: "", Help: "加密通信"},
|
"security": &ctx.Cache{Name: "security(true/false)", Value: "", Help: "加密通信"},
|
||||||
"keyfile": &ctx.Cache{Name: "keyfile", Value: "", Help: "加密通信"},
|
"address": &ctx.Cache{Name: "address", Value: "", Help: "网络地址"},
|
||||||
"address": &ctx.Cache{Name: "网络地址", Value: "", Help: "网络地址"},
|
"nrecv": &ctx.Cache{Name: "nrecv", Value: "0", Help: "接收字节数"},
|
||||||
"nrecv": &ctx.Cache{Name: "nrecv", Value: "0", Help: "网络地址"},
|
"nsend": &ctx.Cache{Name: "nsend", Value: "0", Help: "发送字节数"},
|
||||||
"nsend": &ctx.Cache{Name: "nsend", Value: "0", Help: "网络地址"},
|
|
||||||
}
|
}
|
||||||
c.Configs = map[string]*ctx.Config{}
|
c.Configs = map[string]*ctx.Config{}
|
||||||
|
|
||||||
@ -33,22 +46,17 @@ func (tcp *TCP) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
|
|||||||
s.Context = c
|
s.Context = c
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (tcp *TCP) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||||
// }}}
|
|
||||||
func (tcp *TCP) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|
||||||
return tcp
|
return tcp
|
||||||
}
|
}
|
||||||
|
func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
m.Cap("address", m.Confx("address", arg, 1))
|
m.Cap("address", m.Confx("address", arg, 1))
|
||||||
m.Cap("certfile", m.Confx("certfile", arg, 2))
|
m.Cap("security", m.Confx("security", arg, 2))
|
||||||
m.Cap("keyfile", m.Confx("keyfile", arg, 3))
|
m.Cap("protocol", m.Confx("protocol", arg, 3))
|
||||||
m.Cap("protocol", m.Confx("protocol", arg, 4))
|
|
||||||
|
|
||||||
switch arg[0] {
|
switch arg[0] {
|
||||||
case "dial":
|
case "dial":
|
||||||
if m.Caps("certfile") {
|
if m.Caps("security") {
|
||||||
m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp"))
|
m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp"))
|
||||||
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
|
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
@ -64,20 +72,22 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
m.Log("info", "%s dial %s", m.Cap("nclient"),
|
m.Log("info", "%s dial %s", m.Cap("nclient"),
|
||||||
m.Option("stream", m.Cap("stream", fmt.Sprintf("%s->%s", tcp.LocalAddr(), tcp.RemoteAddr()))))
|
m.Cap("stream", fmt.Sprintf("%s->%s", tcp.LocalAddr(), tcp.RemoteAddr())))
|
||||||
m.Put("option", "io", tcp.Conn).Back(m.Spawn(m.Source()))
|
|
||||||
|
m.Put("option", "io", tcp).Back(m.Spawn(m.Source()))
|
||||||
return false
|
return false
|
||||||
case "accept":
|
case "accept":
|
||||||
c, e := m.Data["io"].(net.Conn)
|
c, e := m.Optionv("io").(net.Conn)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
tcp.Conn = c
|
tcp.Conn = c
|
||||||
|
|
||||||
m.Log("info", "%s accept %s", m.Cap("nclient"),
|
m.Log("info", "%s accept %s", m.Cap("nclient"),
|
||||||
m.Option("stream", m.Cap("stream", fmt.Sprintf("%s<-%s", tcp.LocalAddr(), tcp.RemoteAddr()))))
|
m.Cap("stream", fmt.Sprintf("%s<-%s", tcp.LocalAddr(), tcp.RemoteAddr())))
|
||||||
m.Put("option", "io", tcp.Conn).Back(m.Spawn(m.Source()))
|
|
||||||
|
m.Put("option", "io", tcp).Back(m.Spawn(m.Source()))
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
if m.Caps("certfile") {
|
if m.Caps("security") {
|
||||||
m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp"))
|
m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp"))
|
||||||
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
|
cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile"))
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
@ -92,23 +102,21 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
tcp.Listener = l
|
tcp.Listener = l
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Log("info", "%d listen %v", m.Capi("nlisten"), m.Cap("stream", fmt.Sprintf("%s", tcp.Addr())))
|
m.Log("info", "%d listen %v", m.Capi("nlisten"),
|
||||||
|
m.Cap("stream", fmt.Sprintf("%s", tcp.Addr())))
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
c, e := tcp.Accept()
|
c, e := tcp.Accept()
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
msg := m.Spawn(Index).Put("option", "io", c).Put("option", "source", m.Source())
|
m.Spawn(Index).Put("option", "io", c).Call(func(com *ctx.Message) *ctx.Message {
|
||||||
msg.Call(func(com *ctx.Message) *ctx.Message {
|
|
||||||
return com.Spawn(m.Source())
|
return com.Spawn(m.Source())
|
||||||
}, "accept", c.RemoteAddr().String(), m.Cap("security"), m.Cap("protocol"))
|
}, "accept", c.RemoteAddr().String(), m.Cap("security"), m.Cap("protocol"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
func (tcp *TCP) Close(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (tcp *TCP) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
return false
|
return false
|
||||||
switch tcp.Context {
|
switch tcp.Context {
|
||||||
case m.Target():
|
case m.Target():
|
||||||
@ -136,15 +144,13 @@ func (tcp *TCP) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
|
var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
|
||||||
Caches: map[string]*ctx.Cache{
|
Caches: map[string]*ctx.Cache{
|
||||||
"nlisten": &ctx.Cache{Name: "nlisten", Value: "0", Help: "监听数量"},
|
"nlisten": &ctx.Cache{Name: "nlisten", Value: "0", Help: "监听数量"},
|
||||||
"nclient": &ctx.Cache{Name: "nclient", Value: "0", Help: "连接数量"},
|
"nclient": &ctx.Cache{Name: "nclient", Value: "0", Help: "连接数量"},
|
||||||
},
|
},
|
||||||
Configs: map[string]*ctx.Config{
|
Configs: map[string]*ctx.Config{
|
||||||
"address": &ctx.Config{Name: "address", Value: ":9090", Help: "加密通信"},
|
"address": &ctx.Config{Name: "address", Value: ":9090", Help: "网络地址"},
|
||||||
"security": &ctx.Config{Name: "security(true/false)", Value: "false", Help: "加密通信"},
|
"security": &ctx.Config{Name: "security(true/false)", Value: "false", Help: "加密通信"},
|
||||||
"protocol": &ctx.Config{Name: "protocol(tcp/tcp4/tcp6)", Value: "tcp4", Help: "网络协议"},
|
"protocol": &ctx.Config{Name: "protocol(tcp/tcp4/tcp6)", Value: "tcp4", Help: "网络协议"},
|
||||||
},
|
},
|
||||||
@ -159,53 +165,39 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
|
|||||||
m.Start(fmt.Sprintf("com%d", m.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...)
|
m.Start(fmt.Sprintf("com%d", m.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...)
|
||||||
}},
|
}},
|
||||||
"send": &ctx.Command{Name: "send message", Help: "发送消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"send": &ctx.Command{Name: "send message", Help: "发送消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) && tcp.Conn != nil { // {{{
|
if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) {
|
||||||
tcp.Conn.Write([]byte(arg[0]))
|
tcp.Write([]byte(arg[0]))
|
||||||
m.Capi("nsend", len(arg[0]))
|
}
|
||||||
} // }}}
|
|
||||||
}},
|
}},
|
||||||
"recv": &ctx.Command{Name: "recv size", Help: "接收消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"recv": &ctx.Command{Name: "recv size", Help: "接收消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) && tcp.Conn != nil { // {{{
|
if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) {
|
||||||
size, e := strconv.Atoi(arg[0])
|
n, e := strconv.Atoi(arg[0])
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
buf := make([]byte, n)
|
||||||
|
|
||||||
buf := make([]byte, size)
|
n, _ = tcp.Read(buf)
|
||||||
n, e := tcp.Conn.Read(buf)
|
m.Echo(string(buf[:n]))
|
||||||
m.Assert(e)
|
}
|
||||||
buf = buf[:n]
|
|
||||||
|
|
||||||
m.Echo(string(buf))
|
|
||||||
m.Capi("nrecv", n)
|
|
||||||
} // }}}
|
|
||||||
}},
|
}},
|
||||||
"ifconfig": &ctx.Command{Name: "ifconfig", Help: "网络配置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"ifconfig": &ctx.Command{Name: "ifconfig", Help: "网络配置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
ifs, e := net.Interfaces() // {{{
|
if ifs, e := net.Interfaces(); m.Assert(e) {
|
||||||
m.Assert(e)
|
for _, v := range ifs {
|
||||||
for _, v := range ifs {
|
if ips, e := v.Addrs(); m.Assert(e) {
|
||||||
ips, e := v.Addrs()
|
for _, x := range ips {
|
||||||
m.Assert(e)
|
ip := x.String()
|
||||||
for _, x := range ips {
|
if !strings.Contains(ip, ":") && len(ip) > 0 && len(v.HardwareAddr) > 0 {
|
||||||
ip := x.String()
|
m.Add("append", "index", v.Index)
|
||||||
if !strings.Contains(ip, ":") && len(ip) > 0 && len(v.HardwareAddr) > 0 {
|
m.Add("append", "name", v.Name)
|
||||||
m.Add("append", "index", v.Index)
|
m.Add("append", "hard", v.HardwareAddr)
|
||||||
m.Add("append", "name", v.Name)
|
m.Add("append", "ip", ip)
|
||||||
m.Add("append", "hard", v.HardwareAddr)
|
}
|
||||||
m.Add("append", "ip", ip)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m.Table()
|
||||||
}
|
}
|
||||||
m.Table()
|
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
Index: map[string]*ctx.Context{
|
|
||||||
"void": &ctx.Context{
|
|
||||||
Commands: map[string]*ctx.Command{
|
|
||||||
"listen": &ctx.Command{},
|
|
||||||
"dial": &ctx.Command{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package web // {{{
|
package web
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"contexts"
|
"contexts"
|
||||||
"github.com/gomarkdown/markdown"
|
"github.com/gomarkdown/markdown"
|
||||||
@ -26,14 +26,11 @@ import ( // {{{
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
type MUX interface {
|
type MUX interface {
|
||||||
Handle(string, http.Handler)
|
Handle(string, http.Handler)
|
||||||
HandleFunc(string, func(http.ResponseWriter, *http.Request))
|
HandleFunc(string, func(http.ResponseWriter, *http.Request))
|
||||||
Trans(*ctx.Message, string, func(*ctx.Message, *ctx.Context, string, ...string))
|
Trans(*ctx.Message, string, func(*ctx.Message, *ctx.Context, string, ...string))
|
||||||
}
|
}
|
||||||
|
|
||||||
type WEB struct {
|
type WEB struct {
|
||||||
*http.ServeMux
|
*http.ServeMux
|
||||||
*http.Server
|
*http.Server
|
||||||
@ -44,7 +41,7 @@ type WEB struct {
|
|||||||
*ctx.Context
|
*ctx.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web *WEB) Merge(m *ctx.Message, uri string, arg ...string) string { // {{{
|
func (web *WEB) Merge(m *ctx.Message, uri string, arg ...string) string {
|
||||||
add, e := url.Parse(uri)
|
add, e := url.Parse(uri)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
adds := []string{m.Confx("protocol", add.Scheme, "%s://"), m.Confx("hostname", add.Host)}
|
adds := []string{m.Confx("protocol", add.Scheme, "%s://"), m.Confx("hostname", add.Host)}
|
||||||
@ -86,9 +83,7 @@ func (web *WEB) Merge(m *ctx.Message, uri string, arg ...string) string { // {{{
|
|||||||
|
|
||||||
return strings.Join(adds, "")
|
return strings.Join(adds, "")
|
||||||
}
|
}
|
||||||
|
func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.Context, string, ...string)) {
|
||||||
// }}}
|
|
||||||
func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.Context, string, ...string)) { // {{{
|
|
||||||
web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) {
|
web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) {
|
||||||
msg := m.Spawn()
|
msg := m.Spawn()
|
||||||
msg.TryCatch(msg, true, func(msg *ctx.Message) {
|
msg.TryCatch(msg, true, func(msg *ctx.Message) {
|
||||||
@ -154,9 +149,7 @@ func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.C
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// }}}
|
|
||||||
func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) { // {{{
|
|
||||||
m := web.Message().Log("info", "").Log("info", "%v %s %s", r.RemoteAddr, r.Method, r.URL)
|
m := web.Message().Log("info", "").Log("info", "%v %s %s", r.RemoteAddr, r.Method, r.URL)
|
||||||
|
|
||||||
if m.Confs("logheaders") {
|
if m.Confs("logheaders") {
|
||||||
@ -186,10 +179,7 @@ func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) { // {{{
|
|||||||
m.Log("info", "")
|
m.Log("info", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
|
||||||
// }}}
|
|
||||||
|
|
||||||
func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
|
|
||||||
c.Caches = map[string]*ctx.Cache{}
|
c.Caches = map[string]*ctx.Cache{}
|
||||||
c.Configs = map[string]*ctx.Config{}
|
c.Configs = map[string]*ctx.Config{}
|
||||||
|
|
||||||
@ -198,9 +188,7 @@ func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
|
|||||||
s.cookie = web.cookie
|
s.cookie = web.cookie
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server {
|
||||||
// }}}
|
|
||||||
func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|
||||||
web.Caches["route"] = &ctx.Cache{Name: "请求路径", Value: "/" + web.Context.Name + "/", Help: "请求路径"}
|
web.Caches["route"] = &ctx.Cache{Name: "请求路径", Value: "/" + web.Context.Name + "/", Help: "请求路径"}
|
||||||
web.Caches["register"] = &ctx.Cache{Name: "已初始化(yes/no)", Value: "no", Help: "模块是否已初始化"}
|
web.Caches["register"] = &ctx.Cache{Name: "已初始化(yes/no)", Value: "no", Help: "模块是否已初始化"}
|
||||||
web.Caches["master"] = &ctx.Cache{Name: "服务入口(yes/no)", Value: "no", Help: "服务入口"}
|
web.Caches["master"] = &ctx.Cache{Name: "服务入口(yes/no)", Value: "no", Help: "服务入口"}
|
||||||
@ -219,9 +207,7 @@ func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
|
|||||||
}
|
}
|
||||||
return web
|
return web
|
||||||
}
|
}
|
||||||
|
func (web *WEB) Start(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 {
|
||||||
m.Cap("directory", arg[0])
|
m.Cap("directory", arg[0])
|
||||||
}
|
}
|
||||||
@ -307,9 +293,7 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
func (web *WEB) Close(m *ctx.Message, arg ...string) bool {
|
||||||
// }}}
|
|
||||||
func (web *WEB) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|
||||||
switch web.Context {
|
switch web.Context {
|
||||||
case m.Target():
|
case m.Target():
|
||||||
case m.Source():
|
case m.Source():
|
||||||
@ -317,8 +301,6 @@ func (web *WEB) Close(m *ctx.Message, arg ...string) bool { // {{{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
||||||
Caches: map[string]*ctx.Cache{
|
Caches: map[string]*ctx.Cache{
|
||||||
"nserve": &ctx.Cache{Name: "nserve", Value: "0", Help: "主机数量"},
|
"nserve": &ctx.Cache{Name: "nserve", Value: "0", Help: "主机数量"},
|
||||||
@ -531,7 +513,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
Name: "client address [output [editor]]",
|
Name: "client address [output [editor]]",
|
||||||
Help: "添加请求配置, address: 默认地址, output: 输出路径, editor: 编辑器",
|
Help: "添加请求配置, address: 默认地址, output: 输出路径, editor: 编辑器",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if _, e := m.Target().Server.(*WEB); m.Assert(e) { // {{{
|
if _, e := m.Target().Server.(*WEB); m.Assert(e) {
|
||||||
if len(arg) == 0 {
|
if len(arg) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -553,13 +535,13 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
if m.Conf("editor", "editor", "vim", "文件编辑器"); len(arg) > 2 {
|
if m.Conf("editor", "editor", "vim", "文件编辑器"); len(arg) > 2 {
|
||||||
m.Conf("editor", arg[2])
|
m.Conf("editor", arg[2])
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"cookie": &ctx.Command{
|
"cookie": &ctx.Command{
|
||||||
Name: "cookie [create]|[name [value]]",
|
Name: "cookie [create]|[name [value]]",
|
||||||
Help: "读写请求的Cookie, name: 变量名, value: 变量值",
|
Help: "读写请求的Cookie, name: 变量名, value: 变量值",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { // {{{
|
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) {
|
||||||
switch len(arg) {
|
switch len(arg) {
|
||||||
case 0:
|
case 0:
|
||||||
for k, v := range web.cookie {
|
for k, v := range web.cookie {
|
||||||
@ -583,14 +565,14 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
web.cookie[arg[0]] = &http.Cookie{Name: arg[0], Value: arg[1]}
|
web.cookie[arg[0]] = &http.Cookie{Name: arg[0], Value: arg[1]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"get": &ctx.Command{
|
"get": &ctx.Command{
|
||||||
Name: "get [method GET|POST] [file name filename] url arg...",
|
Name: "get [method GET|POST] [file name filename] url arg...",
|
||||||
Help: "访问服务, method: 请求方法, file: 发送文件, url: 请求地址, arg: 请求参数",
|
Help: "访问服务, method: 请求方法, file: 发送文件, url: 请求地址, arg: 请求参数",
|
||||||
Form: map[string]int{"method": 1, "headers": 2, "file": 2, "body_type": 1, "body": 1, "fields": 1, "value": 1, "json_route": 1, "json_key": 1},
|
Form: map[string]int{"method": 1, "headers": 2, "file": 2, "body_type": 1, "body": 1, "fields": 1, "value": 1, "json_route": 1, "json_key": 1},
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { // {{{
|
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) {
|
||||||
if web.client == nil {
|
if web.client == nil {
|
||||||
web.client = &http.Client{}
|
web.client = &http.Client{}
|
||||||
}
|
}
|
||||||
@ -844,7 +826,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
if m.Table(); len(m.Meta["append"]) == 0 {
|
if m.Table(); len(m.Meta["append"]) == 0 {
|
||||||
m.Echo("%s", string(buf))
|
m.Echo("%s", string(buf))
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"post": &ctx.Command{Name: "post", Help: "访问服务",
|
"post": &ctx.Command{Name: "post", Help: "访问服务",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
@ -864,7 +846,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
case "linux":
|
case "linux":
|
||||||
m.Spawn().Cmd("open", url)
|
m.Spawn().Cmd("open", url)
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"serve": &ctx.Command{
|
"serve": &ctx.Command{
|
||||||
Name: "serve [directory [address [protocol]]]",
|
Name: "serve [directory [address [protocol]]]",
|
||||||
@ -876,7 +858,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
Name: "route script|template|directory route content",
|
Name: "route script|template|directory route content",
|
||||||
Help: "添加响应, script: 脚本响应, template: 模板响应, directory: 目录响应, route: 请求路由, content: 响应内容",
|
Help: "添加响应, script: 脚本响应, template: 模板响应, directory: 目录响应, route: 请求路由, content: 响应内容",
|
||||||
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if mux, ok := m.Target().Server.(MUX); m.Assert(ok) { // {{{
|
if mux, ok := m.Target().Server.(MUX); m.Assert(ok) {
|
||||||
switch len(arg) {
|
switch len(arg) {
|
||||||
case 0:
|
case 0:
|
||||||
for k, v := range m.Target().Commands {
|
for k, v := range m.Target().Commands {
|
||||||
@ -910,26 +892,26 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
mux.Handle(arg[1]+"/", http.StripPrefix(arg[1], http.FileServer(http.Dir(arg[2]))))
|
mux.Handle(arg[1]+"/", http.StripPrefix(arg[1], http.FileServer(http.Dir(arg[2]))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
}},
|
}},
|
||||||
"upload": &ctx.Command{Name: "upload file", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"upload": &ctx.Command{Name: "upload file", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
msg := m.Spawn(m.Target()) // {{{
|
msg := m.Spawn(m.Target())
|
||||||
msg.Cmd("get", "/upload", "method", "POST", "file", "file", arg[0])
|
msg.Cmd("get", "/upload", "method", "POST", "file", "file", arg[0])
|
||||||
m.Copy(msg, "result")
|
m.Copy(msg, "result")
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/library/": &ctx.Command{Name: "/library", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/library/": &ctx.Command{Name: "/library", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
r := m.Optionv("request").(*http.Request) // {{{
|
r := m.Optionv("request").(*http.Request)
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
w := m.Optionv("response").(http.ResponseWriter)
|
||||||
dir := path.Join(m.Conf("library_dir"), m.Option("path"))
|
dir := path.Join(m.Conf("library_dir"), m.Option("path"))
|
||||||
if s, e := os.Stat(dir); e == nil && !s.IsDir() {
|
if s, e := os.Stat(dir); e == nil && !s.IsDir() {
|
||||||
http.ServeFile(w, r, dir)
|
http.ServeFile(w, r, dir)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/travel": &ctx.Command{Name: "/travel", Help: "文件上传", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/travel": &ctx.Command{Name: "/travel", Help: "文件上传", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
// r := m.Optionv("request").(*http.Request) // {{{
|
// r := m.Optionv("request").(*http.Request)
|
||||||
// w := m.Optionv("response").(http.ResponseWriter)
|
// w := m.Optionv("response").(http.ResponseWriter)
|
||||||
|
|
||||||
if !m.Options("dir") {
|
if !m.Options("dir") {
|
||||||
@ -1020,10 +1002,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Append("template", m.Conf("travel_main"), m.Conf("travel_tmpl"))
|
m.Append("template", m.Conf("travel_main"), m.Conf("travel_tmpl"))
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/index/": &ctx.Command{Name: "/index", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/index/": &ctx.Command{Name: "/index", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
r := m.Optionv("request").(*http.Request) // {{{
|
r := m.Optionv("request").(*http.Request)
|
||||||
w := m.Optionv("response").(http.ResponseWriter)
|
w := m.Optionv("response").(http.ResponseWriter)
|
||||||
|
|
||||||
if login := m.Spawn().Cmd("/login"); login.Has("template") {
|
if login := m.Spawn().Cmd("/login"); login.Has("template") {
|
||||||
@ -1065,10 +1047,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
//浏览目录
|
//浏览目录
|
||||||
m.Append("template", m.Append("username"))
|
m.Append("template", m.Append("username"))
|
||||||
m.Option("page_title", "index")
|
m.Option("page_title", "index")
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/create": &ctx.Command{Name: "/create", Help: "创建目录或文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/create": &ctx.Command{Name: "/create", Help: "创建目录或文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
// if check := m.Spawn().Cmd("/share", "/upload", "dir", m.Option("dir")); !check.Results(0) { // {{{
|
// if check := m.Spawn().Cmd("/share", "/upload", "dir", m.Option("dir")); !check.Results(0) {
|
||||||
// m.Copy(check, "append")
|
// m.Copy(check, "append")
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@ -1113,10 +1095,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Append("redirect", m.Option("referer"))
|
m.Append("redirect", m.Option("referer"))
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/share": &ctx.Command{Name: "/share arg...", Help: "资源共享", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/share": &ctx.Command{Name: "/share arg...", Help: "资源共享", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if check := m.Spawn().Cmd("/check", "target", m.Option("module"), m.Optionv("share")); !check.Results(0) { // {{{
|
if check := m.Spawn().Cmd("/check", "target", m.Option("module"), m.Optionv("share")); !check.Results(0) {
|
||||||
m.Copy(check, "append")
|
m.Copy(check, "append")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1205,10 +1187,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
m.Add("append", "to", u)
|
m.Add("append", "to", u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/check": &ctx.Command{Name: "/check arg...", Help: "权限检查, cache|config|command: 接口类型, name: 接口名称, args: 其它参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/check": &ctx.Command{Name: "/check arg...", Help: "权限检查, cache|config|command: 接口类型, name: 接口名称, args: 其它参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if login := m.Spawn().Cmd("/login"); login.Has("template") { // {{{
|
if login := m.Spawn().Cmd("/login"); login.Has("template") {
|
||||||
m.Echo("no").Copy(login, "append")
|
m.Echo("no").Copy(login, "append")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1219,10 +1201,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
}
|
}
|
||||||
|
|
||||||
m.Echo("ok")
|
m.Echo("ok")
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/login": &ctx.Command{Name: "/login", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/login": &ctx.Command{Name: "/login", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if m.Options("sessid") { // {{{
|
if m.Options("sessid") {
|
||||||
if aaa := m.Sess("aaa").Cmd("login", m.Option("sessid")); aaa.Results(0) {
|
if aaa := m.Sess("aaa").Cmd("login", m.Option("sessid")); aaa.Results(0) {
|
||||||
m.Append("redirect", m.Option("referer"))
|
m.Append("redirect", m.Option("referer"))
|
||||||
m.Append("username", aaa.Cap("username"))
|
m.Append("username", aaa.Cap("username"))
|
||||||
@ -1242,10 +1224,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
|
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
m.Append("template", "login")
|
m.Append("template", "login")
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/render": &ctx.Command{Name: "/render index", Help: "模板响应, main: 模板入口, tmpl: 附加模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/render": &ctx.Command{Name: "/render index", Help: "模板响应, main: 模板入口, tmpl: 附加模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
w := m.Optionv("response").(http.ResponseWriter) // {{{
|
w := m.Optionv("response").(http.ResponseWriter)
|
||||||
w.Header().Add("Content-Type", "text/html")
|
w.Header().Add("Content-Type", "text/html")
|
||||||
m.Optioni("ninput", 0)
|
m.Optioni("ninput", 0)
|
||||||
|
|
||||||
@ -1307,10 +1289,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Assert(tpl.ExecuteTemplate(w, "tail", m))
|
m.Assert(tpl.ExecuteTemplate(w, "tail", m))
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/json": &ctx.Command{Name: "/json", Help: "json响应", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/json": &ctx.Command{Name: "/json", Help: "json响应", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
w := m.Optionv("response").(http.ResponseWriter) // {{{
|
w := m.Optionv("response").(http.ResponseWriter)
|
||||||
|
|
||||||
meta := map[string]interface{}{}
|
meta := map[string]interface{}{}
|
||||||
if len(m.Meta["result"]) > 0 {
|
if len(m.Meta["result"]) > 0 {
|
||||||
@ -1337,18 +1319,20 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
|
|||||||
m.Log("json", "won %v", string(b))
|
m.Log("json", "won %v", string(b))
|
||||||
w.Write(b)
|
w.Write(b)
|
||||||
}
|
}
|
||||||
// }}}
|
|
||||||
}},
|
}},
|
||||||
"/paste": &ctx.Command{Name: "/paste", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/paste": &ctx.Command{Name: "/paste", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if login := m.Spawn().Cmd("/login"); login.Has("redirect") {
|
if login := m.Spawn().Cmd("/login"); login.Has("redirect") {
|
||||||
m.Sess("cli").Cmd("system", "tmux", "set-buffer", "-b", "0", m.Option("content"))
|
m.Sess("cli").Cmd("system", "tmux", "set-buffer", "-b", "0", m.Option("content"))
|
||||||
}
|
}
|
||||||
|
|
||||||
}},
|
}},
|
||||||
"/blog": &ctx.Command{Name: "/blog", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/blog": &ctx.Command{Name: "/blog", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if m.Has("title") && m.Has("content") {
|
if m.Has("title") && m.Has("content") {
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Echo("blog service")
|
m.Echo("blog service")
|
||||||
|
|
||||||
}},
|
}},
|
||||||
"/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
"/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 {
|
||||||
|
@ -134,6 +134,24 @@ $ sftp shy@10.0.0.10
|
|||||||
- 公钥文件 ~/.ssh/id_rsa.pub
|
- 公钥文件 ~/.ssh/id_rsa.pub
|
||||||
- 授权公钥 ~/.ssh/authorized_keys
|
- 授权公钥 ~/.ssh/authorized_keys
|
||||||
|
|
||||||
|
#### 编译代码
|
||||||
|
计算机由硬件与软件组成,软件又分为操作系统与应用程序。
|
||||||
|
|
||||||
|
无论是Linux,还是MacOSX,还是Windows,操作系统给应用程序提供了API接口。
|
||||||
|
应用程序通过调用这些API接口,实现各种各样的功能。
|
||||||
|
|
||||||
|
如果现有的工具不能满足需求时,就需要下载工具的源码进行定制编译,或是开发一些模块。
|
||||||
|
|
||||||
|
API
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##### Makefile
|
||||||
|
make命令根据Makefile文件中定义的规则,调用各种命令,来生成目标文件。
|
||||||
|
可以用来调用编译器,将项目的源码文件,编译成可执行文件。
|
||||||
|
将源码文件编译成可执行文件。
|
||||||
|
[Makefile官方文档](https://www.gnu.org/software/make/manual/make.html)
|
||||||
|
<>
|
||||||
|
|
||||||
#### 本地化
|
#### 本地化
|
||||||
|
|
||||||
|
@ -838,12 +838,12 @@ docker以容器的形式,将程序运行的所有环境,打包成一个独
|
|||||||
与VMware或是VirtualBox之类的虚拟机相比,docker更加轻量,docker中的进程和本机进程一样,docker中的文件和本机文件一样,docker只是将它们组织在一起。
|
与VMware或是VirtualBox之类的虚拟机相比,docker更加轻量,docker中的进程和本机进程一样,docker中的文件和本机文件一样,docker只是将它们组织在一起。
|
||||||
而不像虚拟机一样,需要虚拟出一个完整的操作系统,并提供一堆设备驱动程序,一台普通的电脑开几个虚拟机资源就不足了,但docker却像进程一样占有很少的资源,可以运行很多容器。
|
而不像虚拟机一样,需要虚拟出一个完整的操作系统,并提供一堆设备驱动程序,一台普通的电脑开几个虚拟机资源就不足了,但docker却像进程一样占有很少的资源,可以运行很多容器。
|
||||||
|
|
||||||
docker分为企业版EE,社区版CE,对于个人使用社会版即可。更多信息参考:[docker官网](https://docs.docker.com/)
|
docker分为企业版EE,社区版CE,对于个人使用社区版即可。更多信息参考:[docker官网](https://docs.docker.com/)
|
||||||
|
|
||||||
- [Windows版docker下载](https://store.docker.com/editions/community/docker-ce-desktop-windows)
|
- [Windows版docker下载](https://store.docker.com/editions/community/docker-ce-desktop-windows)
|
||||||
- [Mac版docker下载](https://store.docker.com/editions/community/docker-ce-desktop-mac)
|
- [Mac版docker下载](https://store.docker.com/editions/community/docker-ce-desktop-mac)
|
||||||
|
|
||||||
Ubuntu上安装docker
|
Ubuntu上安装docker,还需要将docker官网加到软件源中
|
||||||
```
|
```
|
||||||
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||||
$ sudo add-apt-repository \
|
$ sudo add-apt-repository \
|
||||||
@ -854,256 +854,310 @@ $ sudo apt-get update
|
|||||||
$ sudo apt-get install docker-ce
|
$ sudo apt-get install docker-ce
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 入门体验
|
||||||
|
如下示例,run命令用busybox镜像,启动了docker的一个容器。
|
||||||
```
|
```
|
||||||
$ docker
|
$ docker run -it busybox
|
||||||
Usage: docker [OPTIONS] COMMAND
|
Unable to find image 'busybox:latest' locally
|
||||||
|
latest: Pulling from library/busybox
|
||||||
A self-sufficient runtime for containers
|
8c5a7da1afbc: Pull complete
|
||||||
|
Digest: sha256:cb63aa0641a885f54de20f61d152187419e8f6b159ed11a251a09d115f_f9bd
|
||||||
Options:
|
Status: Downloaded newer image for busybox:latest
|
||||||
--config string Location of client config files (default "/Users/shaoying/.docker")
|
/ #
|
||||||
-D, --debug Enable debug mode
|
|
||||||
-H, --host list Daemon socket(s) to connect to
|
|
||||||
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
|
|
||||||
--tls Use TLS; implied by --tlsverify
|
|
||||||
--tlscacert string Trust certs signed only by this CA (default "/Users/shaoying/.docker/ca.pem")
|
|
||||||
--tlscert string Path to TLS certificate file (default "/Users/shaoying/.docker/cert.pem")
|
|
||||||
--tlskey string Path to TLS key file (default "/Users/shaoying/.docker/key.pem")
|
|
||||||
--tlsverify Use TLS and verify the remote
|
|
||||||
-v, --version Print version information and quit
|
|
||||||
|
|
||||||
Management Commands:
|
|
||||||
checkpoint Manage checkpoints
|
|
||||||
config Manage Docker configs
|
|
||||||
container Manage containers
|
|
||||||
image Manage images
|
|
||||||
network Manage networks
|
|
||||||
node Manage Swarm nodes
|
|
||||||
plugin Manage plugins
|
|
||||||
secret Manage Docker secrets
|
|
||||||
service Manage services
|
|
||||||
stack Manage Docker stacks
|
|
||||||
swarm Manage Swarm
|
|
||||||
system Manage Docker
|
|
||||||
trust Manage trust on Docker images
|
|
||||||
volume Manage volumes
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
attach Attach local standard input, output, and error streams to a running container
|
|
||||||
build Build an image from a Dockerfile
|
|
||||||
commit Create a new image from a container's changes
|
|
||||||
cp Copy files/folders between a container and the local filesystem
|
|
||||||
create Create a new container
|
|
||||||
deploy Deploy a new stack or update an existing stack
|
|
||||||
diff Inspect changes to files or directories on a container's filesystem
|
|
||||||
events Get real time events from the server
|
|
||||||
exec Run a command in a running container
|
|
||||||
export Export a container's filesystem as a tar archive
|
|
||||||
history Show the history of an image
|
|
||||||
images List images
|
|
||||||
import Import the contents from a tarball to create a filesystem image
|
|
||||||
info Display system-wide information
|
|
||||||
inspect Return low-level information on Docker objects
|
|
||||||
kill Kill one or more running containers
|
|
||||||
load Load an image from a tar archive or STDIN
|
|
||||||
login Log in to a Docker registry
|
|
||||||
logout Log out from a Docker registry
|
|
||||||
logs Fetch the logs of a container
|
|
||||||
pause Pause all processes within one or more containers
|
|
||||||
port List port mappings or a specific mapping for the container
|
|
||||||
ps List containers
|
|
||||||
pull Pull an image or a repository from a registry
|
|
||||||
push Push an image or a repository to a registry
|
|
||||||
rename Rename a container
|
|
||||||
restart Restart one or more containers
|
|
||||||
rm Remove one or more containers
|
|
||||||
rmi Remove one or more images
|
|
||||||
run Run a command in a new container
|
|
||||||
save Save one or more images to a tar archive (streamed to STDOUT by default)
|
|
||||||
search Search the Docker Hub for images
|
|
||||||
start Start one or more stopped containers
|
|
||||||
stats Display a live stream of container(s) resource usage statistics
|
|
||||||
stop Stop one or more running containers
|
|
||||||
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
|
|
||||||
top Display the running processes of a container
|
|
||||||
unpause Unpause all processes within one or more containers
|
|
||||||
update Update configuration of one or more containers
|
|
||||||
version Show the Docker version information
|
|
||||||
wait Block until one or more containers stop, then print their exit codes
|
|
||||||
|
|
||||||
Run 'docker COMMAND --help' for more information on a command.
|
|
||||||
```
|
```
|
||||||
|
这里本机并没有busybox的镜像,所以docker自动从dockhub上,下载了busybox的镜像,并用这个镜像启动了一个容器。
|
||||||
|
像github共享代码一样,dockhub上也共享了各种系统镜像,用户可以自由的下载与上传。
|
||||||
|
|
||||||
|
run命令需要一个参数,指定镜像的名称与版本,这里镜像的名字为busybox,默认的版本为latest,即最新版。
|
||||||
|
busybox是将Unix下的常用命令经过挑选裁剪集成到一个程序中,搭配Linux内核就可以做出一个小型的操作系统,在嵌入式领域应用广泛。
|
||||||
|
体积小到只有1M左右,下载很快,所以这里用做示例。更多信息参考[busybox官网](https://busybox.net/)
|
||||||
|
|
||||||
|
"/ #",看到最后一行的的命令提示符,就知道容器已经启动了,就可以在这个容器的shell中,执行各种命令与操作了。最后用Ctrl+D或关闭终端窗口,就可以结束容器。
|
||||||
|
再次运行run,又可以重新启动容器。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
如下示例,除了交互式启动容器,还可以用守护的方式启动容器。
|
||||||
```
|
```
|
||||||
$ docker
|
$ docker run -dt --name demo busybox
|
||||||
Usage: docker [OPTIONS] COMMAND
|
d71c8e37bcc153db239f8b1eccb5fa53d202df84d3ffa7ae4e7f8c051d0d481a
|
||||||
|
|
||||||
A self-sufficient runtime for containers
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--config string Location of client config files (default "/Users/shaoying/.docker")
|
|
||||||
-D, --debug Enable debug mode
|
|
||||||
-H, --host list Daemon socket(s) to connect to
|
|
||||||
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
|
|
||||||
--tls Use TLS; implied by --tlsverify
|
|
||||||
--tlscacert string Trust certs signed only by this CA (default "/Users/shaoying/.docker/ca.pem")
|
|
||||||
--tlscert string Path to TLS certificate file (default "/Users/shaoying/.docker/cert.pem")
|
|
||||||
--tlskey string Path to TLS key file (default "/Users/shaoying/.docker/key.pem")
|
|
||||||
--tlsverify Use TLS and verify the remote
|
|
||||||
-v, --version Print version information and quit
|
|
||||||
|
|
||||||
Management Commands:
|
|
||||||
checkpoint Manage checkpoints
|
|
||||||
node Manage Swarm nodes
|
|
||||||
plugin Manage plugins
|
|
||||||
secret Manage Docker secrets
|
|
||||||
service Manage services
|
|
||||||
stack Manage Docker stacks
|
|
||||||
swarm Manage Swarm
|
|
||||||
trust Manage trust on Docker images
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
attach Attach local standard input, output, and error streams to a running container
|
|
||||||
build Build an image from a Dockerfile
|
|
||||||
commit Create a new image from a container's changes
|
|
||||||
cp Copy files/folders between a container and the local filesystem
|
|
||||||
create Create a new container
|
|
||||||
deploy Deploy a new stack or update an existing stack
|
|
||||||
diff Inspect changes to files or directories on a container's filesystem
|
|
||||||
events Get real time events from the server
|
|
||||||
exec Run a command in a running container
|
|
||||||
export Export a container's filesystem as a tar archive
|
|
||||||
history Show the history of an image
|
|
||||||
images List images
|
|
||||||
import Import the contents from a tarball to create a filesystem image
|
|
||||||
info Display system-wide information
|
|
||||||
inspect Return low-level information on Docker objects
|
|
||||||
kill Kill one or more running containers
|
|
||||||
load Load an image from a tar archive or STDIN
|
|
||||||
login Log in to a Docker registry
|
|
||||||
logout Log out from a Docker registry
|
|
||||||
logs Fetch the logs of a container
|
|
||||||
pause Pause all processes within one or more containers
|
|
||||||
port List port mappings or a specific mapping for the container
|
|
||||||
ps List containers
|
|
||||||
pull Pull an image or a repository from a registry
|
|
||||||
push Push an image or a repository to a registry
|
|
||||||
rename Rename a container
|
|
||||||
restart Restart one or more containers
|
|
||||||
rm Remove one or more containers
|
|
||||||
rmi Remove one or more images
|
|
||||||
run Run a command in a new container
|
|
||||||
save Save one or more images to a tar archive (streamed to STDOUT by default)
|
|
||||||
search Search the Docker Hub for images
|
|
||||||
start Start one or more stopped containers
|
|
||||||
stats Display a live stream of container(s) resource usage statistics
|
|
||||||
stop Stop one or more running containers
|
|
||||||
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
|
|
||||||
top Display the running processes of a container
|
|
||||||
unpause Unpause all processes within one or more containers
|
|
||||||
update Update configuration of one or more containers
|
|
||||||
version Show the Docker version information
|
|
||||||
wait Block until one or more containers stop, then print their exit codes
|
|
||||||
|
|
||||||
Run 'docker COMMAND --help' for more information on a command.
|
|
||||||
```
|
```
|
||||||
|
- "-dt",指定容器守护的方式运行,即使终端窗口关闭了,守护式的容器会在后台一直运行,可以被反复连接使用。
|
||||||
|
- "--name demo",指定了容器的名字为demo,每个容器启动后docker会生成一个sha256的哈希值,如这里的"d71c8e37bcc153db239f8b1eccb5fa53d202df84d3ffa7ae4e7f8c051d0d481a"
|
||||||
|
在之后的命令中,参数中需要指定容器的地方,都可以这个sha256的哈希值,也可以只写出前几位。但为了方便记忆,可以给容器指定名字。
|
||||||
|
- "busybox",指定镜像名字与版本
|
||||||
|
|
||||||
镜像管理
|
如下示例,ps命令可以查看正在运行的容器。
|
||||||
image Manage images
|
|
||||||
|
|
||||||
容器管理
|
|
||||||
container Manage containers
|
|
||||||
|
|
||||||
配置管理
|
|
||||||
config Manage Docker configs
|
|
||||||
|
|
||||||
系统管理
|
|
||||||
system Manage Docker
|
|
||||||
|
|
||||||
网络管理
|
|
||||||
network Manage networks
|
|
||||||
|
|
||||||
磁盘管理
|
|
||||||
volume Manage volumes
|
|
||||||
|
|
||||||
#### docker镜像管理
|
|
||||||
|
|
||||||
- 查看镜像 docker image ls
|
|
||||||
- 下载镜像 docker image pull
|
|
||||||
|
|
||||||
刚安装docker后,查看镜像列表,如下为空。
|
|
||||||
```
|
|
||||||
$ docker image ls
|
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
||||||
```
|
|
||||||
像github管理代码仓库一样,docker hub上也存放了很多镜像,用户可以自由的下载与上传各种镜像。
|
|
||||||
如下示例,下载一个busybox镜像。busybox是将Unix下的常用命令经过挑选裁剪集成一个程序中,搭配Linux内核就可以做出一个小型的操作系统,在嵌入式领域应用广泛。
|
|
||||||
体积很小不到1M,下载很快,所以这里用做示例。更多信息参考[busybox官网](https://busybox.net/)
|
|
||||||
```
|
|
||||||
$ docker image pull busybox
|
|
||||||
```
|
|
||||||
下载完成后,再查看镜像列表,就会看到busybox镜像相关的信息。
|
|
||||||
```
|
|
||||||
$ docker image ls
|
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
||||||
busybox latest e1ddd7948a1c 6 weeks ago 1.16MB
|
|
||||||
```
|
|
||||||
#### docker容器管理
|
|
||||||
|
|
||||||
- 查看容器 docker ps
|
|
||||||
- 启动容器 docker run
|
|
||||||
- 停止容器 docker exec
|
|
||||||
- 停止容器 docker stop
|
|
||||||
|
|
||||||
如下示例,查看容器列表,因为还没启动任何容器,所以这里为空。
|
|
||||||
```
|
```
|
||||||
$ docker ps
|
$ docker ps
|
||||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
d71c8e37bcc1 busybox "sh" 14 seconds ago Up 13 seconds demo
|
||||||
```
|
```
|
||||||
如下示例,用busybox:latest镜像,启动一个容器,并调用sh命令。
|
如下示例,top命令可以查看某容器中运行的进程
|
||||||
```
|
```
|
||||||
$ docker run --name demo -dt busybox:latest sh
|
$ docker top demo
|
||||||
29ff6b8343c4a2c57eab297e74e62422ab9bbd481d69f5ebf108f4aa23ae835c
|
PID USER TIME COMMAND
|
||||||
```
|
4163 root 0:00 sh
|
||||||
其中,-d 指用守护的方式启动,与交互式 -i 不同,守护式启动,容器可以一直运行,不会因为终端容器关闭而停止。
|
|
||||||
--name参数,指定容器的名字为demo,docker中标识容器有两种方式,一是通过ID查找容器,二是通过NAMES查找容器,为了方便记忆与查找,建议启动容器时加上名字参数。
|
|
||||||
|
|
||||||
如下示例,再次查看容器列表,看到容器已经启动。
|
|
||||||
```
|
|
||||||
$ docker ps
|
|
||||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
||||||
29ff6b8343c4 busybox:latest "sh" 4 minutes ago Up 4 minutes demo
|
|
||||||
```
|
```
|
||||||
|
|
||||||
连接容器demo,调用命令解析器sh。这样就连接上了容器的命令行,可以执行各种命令。
|
如下示例,exec可以在容器中运行各种命令,并将命令输出到当前终端。
|
||||||
|
```
|
||||||
|
$ docker exec demo uname
|
||||||
|
Linux
|
||||||
|
$ docker exec demo hostname
|
||||||
|
d71c8e37bcc1
|
||||||
|
```
|
||||||
|
如下示例,还可以连接容器,启动一个交互shell。Ctrl+D或是关闭终端窗口,只会结束当前shell,容器依然还在后台继续运行。还可以被反复连接。
|
||||||
```
|
```
|
||||||
$ docker exec -it demo sh
|
$ docker exec -it demo sh
|
||||||
#
|
/ #
|
||||||
|
```
|
||||||
|
如下示例,还可以对容器进行重命名。可以用ps命令查看,新名字已经生效。
|
||||||
|
```
|
||||||
|
$ docker rename demo demo1
|
||||||
```
|
```
|
||||||
|
|
||||||
容器的停止,退出连接后,容器依然在后台运行,可以反复被连接。如果想停止容器的运行就用stop命令。
|
容器中的根文件系统与本机的文件系统是完全隔离的,所以才能提供给容器中应用一个独立的运行环境。
|
||||||
|
|
||||||
|
如下示例,可以将本机文件复制到容器中。
|
||||||
```
|
```
|
||||||
$ docker stop demo
|
$ docker cp ~/.vimrc demo1:/root
|
||||||
|
$ docker exec demo1 ls -a /root
|
||||||
|
.
|
||||||
|
..
|
||||||
|
.vimrc
|
||||||
|
```
|
||||||
|
如下示例,可以将容器中文件复制到本机。
|
||||||
|
```
|
||||||
|
$ docker cp demo1:/root vimrc
|
||||||
|
$ ls
|
||||||
|
vimrc
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 挂载文件
|
如下示例,停止容器
|
||||||
之前启动的容器都是与本机之间没有什么交互,是一个完全独立的运行环境。
|
|
||||||
如果需要容器与本机交互一些文件,就可以在启动容器时指定文件参数。
|
|
||||||
```
|
```
|
||||||
$ docker run --name demo1 -v/Users/shaoying:/home/shaoying -dt busybox:latest sh
|
$ docker stop demo1
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 端口映射
|
ps命令默认只查看正在运行的容器,如果要查看已经停止的容器可以加参数-a
|
||||||
|
```
|
||||||
|
$ docker ps -a
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
513a5e1fc6f4 busybox "sh" 4 minutes ago Exited (137) 3 seconds ago demo1
|
||||||
|
```
|
||||||
|
|
||||||
|
如下示例,已经停止的容器,还可以再启动,继续运行。
|
||||||
|
```
|
||||||
|
$ docker start demo1
|
||||||
|
```
|
||||||
|
|
||||||
|
如下示例,如果确定已经停止的容器,不会再次启动使用,可以删除掉。
|
||||||
|
```
|
||||||
|
$ docker rm demo1
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 镜像管理
|
||||||
|
```
|
||||||
|
docker images
|
||||||
|
image Manage images
|
||||||
|
|
||||||
|
images List images
|
||||||
|
search Search the Docker Hub for images
|
||||||
|
pull Pull an image or a repository from a registry
|
||||||
|
push Push an image or a repository to a registry
|
||||||
|
save Save one or more images to a tar archive (streamed to STDOUT by default)
|
||||||
|
load Load an image from a tar archive or STDIN
|
||||||
|
rmi Remove one or more images
|
||||||
|
|
||||||
|
history Show the history of an image
|
||||||
|
build Build an image from a Dockerfile
|
||||||
|
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 容器管理
|
||||||
|
```
|
||||||
|
stats Display a live stream of container(s) resource usage statistics
|
||||||
|
attach Attach local standard input, output, and error streams to a running container
|
||||||
|
container Manage containers
|
||||||
|
commit Create a new image from a container's changes
|
||||||
|
diff Inspect changes to files or directories on a container's filesystem
|
||||||
|
kill Kill one or more running containers
|
||||||
|
wait Block until one or more containers stop, then print their exit codes
|
||||||
|
create Create a new container
|
||||||
|
pause Pause all processes within one or more containers
|
||||||
|
unpause Unpause all processes within one or more containers
|
||||||
|
export Export a container's filesystem as a tar archive
|
||||||
|
import Import the contents from a tarball to create a filesystem image
|
||||||
|
logs Fetch the logs of a container
|
||||||
|
restart Restart one or more containers
|
||||||
|
update Update configuration of one or more containers
|
||||||
|
volume Manage volumes
|
||||||
|
network Manage networks
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 系统管理
|
||||||
|
```
|
||||||
|
deploy Deploy a new stack or update an existing stack
|
||||||
|
version Show the Docker version information
|
||||||
|
system Manage Docker
|
||||||
|
info Display system-wide information
|
||||||
|
login Log in to a Docker registry
|
||||||
|
logout Log out from a Docker registry
|
||||||
|
inspect Return low-level information on Docker objects
|
||||||
|
secret Manage Docker secrets
|
||||||
|
trust Manage trust on Docker images
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 集群管理
|
||||||
|
```
|
||||||
|
config Manage Docker configs
|
||||||
|
checkpoint Manage checkpoints
|
||||||
|
plugin Manage plugins
|
||||||
|
service Manage services
|
||||||
|
swarm Manage Swarm
|
||||||
|
node Manage Swarm nodes
|
||||||
|
stack Manage Docker stacks
|
||||||
|
```
|
||||||
|
|
||||||
|
### git使用
|
||||||
|
软件的开发是不断的迭代,不断的优化,不断的升级,是一个循序渐进的过程。
|
||||||
|
所以需要对代码进行版本管理,记录每次提交的代码,可以随时查看变化与切换版本。
|
||||||
|
|
||||||
|
软件开发有时需要同时进行多个任务,如在开发新功能时,需要修复线上bug,所以需要分支管理。
|
||||||
|
一般一个项目中至少会有三种分支:master、feature、bugfix。
|
||||||
|
|
||||||
|
此外软件开发的项目都一般是由团队完成,要多人协作共同完成功能开发,所以需要仓库管理,管理多人的代码。
|
||||||
|
|
||||||
|
git就是这样一种开源的代码管理工具,可以用来管理代码的版本、分支、仓库等。
|
||||||
|
|
||||||
### git入门
|
|
||||||
Mac上自带git,不需要安装。
|
Mac上自带git,不需要安装。
|
||||||
Windows上安装了的git-scm,也集成了git,也不需要单独安装。
|
Windows上安装了的git-scm,也集成了git,也不需要单独安装。
|
||||||
但Ubuntu需要自己安装一下。
|
但Ubuntu需要自己安装一下。
|
||||||
```
|
```
|
||||||
$ sudo apt-get install git
|
$ sudo apt-get install git
|
||||||
```
|
```
|
||||||
|
#### git 基础入门
|
||||||
|
git help tutorial
|
||||||
|
git help everyday
|
||||||
|
git help workflows
|
||||||
|
git help glossary
|
||||||
|
|
||||||
|
git是一个命令集合,有很多子命令,可以通过help命令来查看。
|
||||||
|
```
|
||||||
|
$ git help
|
||||||
|
```
|
||||||
|
|
||||||
|
git init
|
||||||
|
git status
|
||||||
|
git diff
|
||||||
|
git add
|
||||||
|
git mv
|
||||||
|
git rm
|
||||||
|
git reset
|
||||||
|
git commit
|
||||||
|
git checkout
|
||||||
|
git blame
|
||||||
|
git log
|
||||||
|
git tag
|
||||||
|
|
||||||
|
git branch
|
||||||
|
git merge
|
||||||
|
git rebase
|
||||||
|
|
||||||
|
git config
|
||||||
|
git clone
|
||||||
|
git remote
|
||||||
|
git revert
|
||||||
|
git fetch
|
||||||
|
git pull
|
||||||
|
git push
|
||||||
|
|
||||||
|
git bisect
|
||||||
|
git grep
|
||||||
|
git show
|
||||||
|
|
||||||
|
|
||||||
|
add merge-octopus
|
||||||
|
add--interactive merge-one-file
|
||||||
|
am merge-ours
|
||||||
|
annotate merge-recursive
|
||||||
|
apply merge-resolve
|
||||||
|
archimport merge-subtree
|
||||||
|
archive merge-tree
|
||||||
|
bisect mergetool
|
||||||
|
bisect--helper mktag
|
||||||
|
blame mktree
|
||||||
|
branch mv
|
||||||
|
bundle name-rev
|
||||||
|
cat-file notes
|
||||||
|
check-attr p4
|
||||||
|
check-ignore pack-objects
|
||||||
|
check-mailmap pack-redundant
|
||||||
|
check-ref-format pack-refs
|
||||||
|
checkout patch-id
|
||||||
|
checkout-index prune
|
||||||
|
cherry prune-packed
|
||||||
|
cherry-pick pull
|
||||||
|
citool push
|
||||||
|
clean quiltimport
|
||||||
|
clone read-tree
|
||||||
|
column rebase
|
||||||
|
commit receive-pack
|
||||||
|
commit-tree reflog
|
||||||
|
config relink
|
||||||
|
count-objects remote
|
||||||
|
credential remote-ext
|
||||||
|
credential-cache remote-fd
|
||||||
|
credential-cache--daemon remote-ftp
|
||||||
|
credential-osxkeychain remote-ftps
|
||||||
|
credential-store remote-http
|
||||||
|
cvsexportcommit remote-https
|
||||||
|
cvsimport remote-testsvn
|
||||||
|
cvsserver repack
|
||||||
|
daemon replace
|
||||||
|
describe request-pull
|
||||||
|
diff rerere
|
||||||
|
diff-files reset
|
||||||
|
diff-index rev-list
|
||||||
|
diff-tree rev-parse
|
||||||
|
difftool revert
|
||||||
|
difftool--helper rm
|
||||||
|
fast-export send-email
|
||||||
|
fast-import send-pack
|
||||||
|
fetch sh-i18n--envsubst
|
||||||
|
fetch-pack shell
|
||||||
|
filter-branch shortlog
|
||||||
|
fmt-merge-msg show
|
||||||
|
for-each-ref show-branch
|
||||||
|
format-patch show-index
|
||||||
|
fsck show-ref
|
||||||
|
fsck-objects stage
|
||||||
|
gc stash
|
||||||
|
get-tar-commit-id status
|
||||||
|
grep stripspace
|
||||||
|
gui--askpass submodule
|
||||||
|
hash-object submodule--helper
|
||||||
|
help subtree
|
||||||
|
http-backend svn
|
||||||
|
http-fetch symbolic-ref
|
||||||
|
http-push tag
|
||||||
|
imap-send unpack-file
|
||||||
|
index-pack unpack-objects
|
||||||
|
init update-index
|
||||||
|
init-db update-ref
|
||||||
|
instaweb update-server-info
|
||||||
|
interpret-trailers upload-archive
|
||||||
|
log upload-pack
|
||||||
|
ls-files var
|
||||||
|
ls-remote verify-commit
|
||||||
|
ls-tree verify-pack
|
||||||
|
mailinfo verify-tag
|
||||||
|
mailsplit web--browse
|
||||||
|
merge whatchanged
|
||||||
|
merge-base worktree
|
||||||
|
merge-file write-tree
|
||||||
|
merge-index
|
||||||
|
|
||||||
### vim入门
|
### vim入门
|
||||||
Mac上自带vim,不需要安装。
|
Mac上自带vim,不需要安装。
|
||||||
Windows上安装了的git-scm,也集成了vim,也不需要单独安装。
|
Windows上安装了的git-scm,也集成了vim,也不需要单独安装。
|
||||||
|
Loading…
x
Reference in New Issue
Block a user