diff --git a/.idea/learninggo.iml b/.idea/learninggo.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/learninggo.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..2a89827
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..b87b5bb
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,370 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ta
+ string
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ buf.Len()
+ go
+ EXPRESSION
+
+
+ len("{")
+ go
+ EXPRESSION
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/json/customize_unmarshal/main.go b/json/customize_unmarshal/main.go
new file mode 100644
index 0000000..a89ed14
--- /dev/null
+++ b/json/customize_unmarshal/main.go
@@ -0,0 +1,118 @@
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+)
+
+// http://gregtrowbridge.com/golang-json-serialization-with-interfaces/
+type ColoredThing interface {
+ Color() string
+}
+
+type ColorfulEcosystem struct {
+ Things []ColoredThing `json:"things"`
+}
+
+func (ce *ColorfulEcosystem) UnmarshalJSON(b []byte) error {
+ var objMap map[string]*json.RawMessage
+ err := json.Unmarshal(b, &objMap)
+ if err != nil {
+ return err
+ }
+ var rawMessages []*json.RawMessage
+ err = json.Unmarshal(*objMap["things"], &rawMessages)
+ if err != nil {
+ return err
+ }
+ ce.Things = make([]ColoredThing, len(rawMessages))
+ var m map[string]string
+
+ for idx, rawMessage := range rawMessages {
+ err = json.Unmarshal(*rawMessage, &m)
+ if err != nil {
+ return err
+ }
+
+ if m["type"] == "plant" {
+ var p Plant
+ err := json.Unmarshal(*rawMessage, &p)
+ if err != nil {
+ return err
+ }
+ ce.Things[idx] = &p
+ } else if m["type"] == "animal" {
+ var a Animal
+ err := json.Unmarshal(*rawMessage, &a)
+ if err != nil {
+ return err
+ }
+ ce.Things[idx] = &a
+ } else {
+ return errors.New("unsupported type " + m["type"])
+ }
+ }
+ return nil
+}
+
+type Plant struct {
+ MyColor string `json:"color"`
+}
+
+type Animal struct {
+ MyColor string `json:"color"`
+}
+
+func (p *Plant) Color() string {
+ return p.MyColor
+}
+
+func (a *Plant) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]string{
+ "type": "plant",
+ "color": a.Color(),
+ })
+}
+
+func (a *Animal) Color() string {
+ return a.MyColor
+}
+
+func (a *Animal) MarshalJSON() ([]byte, error) {
+ return json.Marshal(map[string]string{
+ "type": "animal",
+ "color": a.Color(),
+ })
+}
+
+func main() {
+ fern := &Plant{MyColor: "green"}
+ flower := &Plant{MyColor: "purple"}
+
+ panther := &Animal{MyColor: "black"}
+ lizard := &Animal{MyColor: "green"}
+
+ // Then let's create a ColorfulEcosystem
+ colorfulEcosystem := ColorfulEcosystem{
+ Things: []ColoredThing{
+ fern,
+ flower,
+ panther,
+ lizard,
+ },
+ }
+
+ byteSlice, _ := json.Marshal(colorfulEcosystem)
+ fmt.Println(string(byteSlice))
+
+ ce := ColorfulEcosystem{}
+
+ err := json.Unmarshal(byteSlice, &ce)
+ if err != nil {
+ panic(err)
+ }
+ for _, c := range ce.Things {
+ fmt.Println(c.Color())
+ }
+}
diff --git a/json/marshal/main.go b/json/marshal/main.go
new file mode 100644
index 0000000..b5d43d9
--- /dev/null
+++ b/json/marshal/main.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Plant struct {
+ MyColor string
+}
+
+func (p Plant) MarshalJSON() ([]byte, error) {
+ m := make(map[string]string)
+ m["type"] = "plant"
+ m["color"] = p.MyColor
+ return json.Marshal(m)
+}
+
+type Animal struct {
+ MyColor string
+}
+
+func main() {
+ p := Plant{MyColor: "green"}
+ a := Animal{MyColor: "red"}
+
+ b, _ := json.Marshal(p)
+ ba, _ := json.Marshal(a)
+
+ fmt.Println(string(b))
+ fmt.Println(string(ba))
+
+}
diff --git a/net/.idea/misc.xml b/net/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/net/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/net/.idea/modules.xml b/net/.idea/modules.xml
new file mode 100644
index 0000000..96da8c6
--- /dev/null
+++ b/net/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/net/.idea/net.iml b/net/.idea/net.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/net/.idea/net.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/net/.idea/workspace.xml b/net/.idea/workspace.xml
new file mode 100644
index 0000000..85a3c04
--- /dev/null
+++ b/net/.idea/workspace.xml
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/server/main.go
+ 71
+
+
+
+
+ file:///usr/local/go/src/net/net.go
+ 173
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/net/client/main.go b/net/client/main.go
new file mode 100644
index 0000000..584d7f1
--- /dev/null
+++ b/net/client/main.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "time"
+)
+
+func main() {
+
+ c, err := net.Dial("unix", "/tmp/test.sock")
+ if err != nil {
+ panic(err)
+ }
+ defer c.Close()
+
+ reader(c)
+ for {
+ r := bufio.NewReader(os.Stdin)
+ fmt.Println("text to send")
+ text, _ := r.ReadString('\n')
+ fmt.Println(text)
+ c.Write([]byte(text))
+
+ bufio.NewReader(c)
+ _, err = c.Write([]byte("hello"))
+ if err != nil {
+ panic(err)
+ }
+ time.Sleep(2 * time.Second)
+ }
+}
+
+func reader(r io.Reader) {
+ buf := make([]byte, 1024)
+ for {
+ fmt.Println("read from conn")
+ n, err := r.Read(buf[:])
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ fmt.Println("got data", string(buf[0:n]))
+ }
+}
diff --git a/net/server/main.go b/net/server/main.go
new file mode 100644
index 0000000..c8eb5c4
--- /dev/null
+++ b/net/server/main.go
@@ -0,0 +1,83 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+)
+
+func main() {
+
+ var l net.Listener
+ _, err := os.Stat("/tmp/test.sock")
+ if os.IsNotExist(err) {
+ l, err = net.Listen("unix", "/tmp/test.sock")
+ }
+ f, _ := l.(*net.UnixListener).File()
+ l2, err := net.FileListener(f)
+ if err != nil {
+ panic(err)
+ }
+ sigc := make(chan os.Signal, 1)
+ signal.Notify(sigc, os.Interrupt, syscall.SIGTERM, syscall.SIGPIPE)
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func(ln net.Listener, c chan os.Signal) {
+ sig := <-c
+ log.Printf("Caught signal %s: shutting down.", sig)
+ ln.Close()
+ os.Exit(0)
+ }(l, sigc)
+ go func() {
+ for {
+ fmt.Println("waiting for l2 to accept connection")
+ conn, err := l2.Accept()
+ if err != nil {
+ fmt.Printf("failed to accept connection %+v\n", err)
+ continue
+ }
+ fmt.Println("connection accepted from listener l2")
+ go handleConn(conn)
+ }
+ }()
+ go func() {
+ n := 0
+ for {
+ if n = n + 1; n == 5 {
+ break
+ }
+ fmt.Println("waiting for l1 to accept connection")
+ conn, err := l.Accept()
+ if err != nil {
+ fmt.Printf("failed to accept connection %+v\n", err)
+ continue
+ }
+ fmt.Println("connection accepted from listener l1")
+ go handleConn(conn)
+ }
+
+ }()
+ wg.Wait()
+}
+
+func handleConn(c net.Conn) {
+ defer c.Close()
+ net.Pipe()
+ buf := make([]byte, 1024)
+ for {
+ n, err := c.Read(buf[0:])
+ if err != nil {
+ return
+ }
+ data := buf[0:n]
+ fmt.Println(string(data))
+ _, err = c.Write([]byte("write from server"))
+ if err != nil {
+ fmt.Println("write error: ", err)
+ }
+ }
+}
diff --git a/pipestdio/main.go b/pipestdio/main.go
new file mode 100644
index 0000000..0d0a479
--- /dev/null
+++ b/pipestdio/main.go
@@ -0,0 +1,21 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+)
+
+func main() {
+
+ r := bufio.NewReader(os.Stdin)
+ var b [1024]byte
+ for {
+ n, err := r.Read(b[:])
+ if err != nil {
+ break
+ }
+ fmt.Print(string(b[0:n]))
+ }
+
+}
diff --git a/pipestdio/namedpipe/Dockerfile b/pipestdio/namedpipe/Dockerfile
new file mode 100644
index 0000000..3746dbd
--- /dev/null
+++ b/pipestdio/namedpipe/Dockerfile
@@ -0,0 +1,21 @@
+FROM golang:1.10.3-alpine3.8 AS builder
+
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories
+
+RUN apk update && \
+ apk add git build-base && \
+ rm -rf /var/cache/apk/* && \
+ mkdir -p "$GOPATH/src/gitlab.alipay-inc.com/basement/cube/logcollector"
+
+ADD . "$GOPATH/src/gitlab.alipay-inc.com/basement/cube/logcollector"
+
+RUN cd "$GOPATH/src/gitlab.alipay-inc.com/basement/cube/logcollector" && \
+ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a --installsuffix cgo --ldflags="-s" -o /logcollector ./
+
+FROM alpine:3.8
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories
+RUN apk add --update ca-certificates
+
+COPY --from=builder /logcollector /bin/logcollector
+
+ENTRYPOINT ["/bin/logcollector"]
\ No newline at end of file
diff --git a/pipestdio/namedpipe/main.go b/pipestdio/namedpipe/main.go
new file mode 100644
index 0000000..5232887
--- /dev/null
+++ b/pipestdio/namedpipe/main.go
@@ -0,0 +1,90 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "os/signal"
+ "path/filepath"
+ "syscall"
+)
+
+func main() {
+ // createLogEntry()
+ // appendLog()
+ namedPipe()
+}
+
+func namedPipe() {
+ namedPipe := filepath.Join("/var/applogs", "stdout")
+ fmt.Println(namedPipe)
+ syscall.Mkfifo(namedPipe, 0600)
+
+ stdout, _ := os.OpenFile(namedPipe, os.O_RDONLY, 0600)
+ defer stdout.Close()
+ fmt.Println("reading")
+
+ sigc := make(chan os.Signal, 1)
+ signal.Notify(sigc, os.Interrupt, syscall.SIGTERM, syscall.SIGPIPE)
+ go func(c chan os.Signal) {
+ sig := <-c
+ log.Printf("Caught signal %s: shutting down.", sig)
+ os.Exit(0)
+ }(sigc)
+
+ var b [512]byte
+ httpClient := http.DefaultClient
+ for {
+ fmt.Println("reading from namedpipe")
+ n, err := stdout.Read(b[:])
+ if err != nil {
+ fmt.Println(err)
+ continue
+ }
+ req, _ := http.NewRequest("PUT", "https://tfapi.alipay.com/api/v1/logs/5be2f1890ab517886f7fff86", bytes.NewReader(b[0:n]))
+ resp, err := httpClient.Do(req)
+ if err != nil {
+ panic(err)
+ }
+ resp.Body.Close()
+ }
+}
+
+func createLogEntry() {
+ httpClient := &http.Client{}
+ // b, _ := json.Marshal(struct {
+ // append bool
+ // }{
+ // append: true,
+ // })
+
+ req, _ := http.NewRequest("POST", "https://tfapi.alipay.com/api/v1/logs?append", nil)
+ req.Header.Set("Content-Type", "application/json")
+ resp, err := httpClient.Do(req)
+ if err != nil {
+ panic(err)
+ }
+ defer resp.Body.Close()
+
+ body, err := ioutil.ReadAll(resp.Body)
+ fmt.Println(resp.StatusCode)
+ if err != nil {
+ panic(err)
+ }
+ fmt.Println(string(body))
+}
+
+func appendLog() {
+ httpClient := http.DefaultClient
+ req, _ := http.NewRequest("PUT", "https://tfapi.alipay.com/api/v1/logs/5be2ddfff8b5f7fa3ff36831", bytes.NewReader([]byte("hello world")))
+ resp, err := httpClient.Do(req)
+ if err != nil {
+ panic(err)
+ }
+ defer resp.Body.Close()
+ fmt.Println(resp.StatusCode)
+
+}
diff --git a/syscall/container/container b/syscall/container/container
deleted file mode 100755
index c770028..0000000
Binary files a/syscall/container/container and /dev/null differ
diff --git a/syscall/container/main_linux.go b/syscall/container/main_linux.go
index dfa9e06..aec2ab3 100644
--- a/syscall/container/main_linux.go
+++ b/syscall/container/main_linux.go
@@ -4,8 +4,11 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
"os/exec"
+ "path/filepath"
+ "strconv"
"syscall"
)
@@ -31,6 +34,16 @@ func run() {
cmd.Stderr = os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
+ // use user ns enable you to do something with root privilege inside container
+ // notice that at this moment you can not use cgroup along with NEWUSER flag
+ // | syscall.CLONE_NEWUSER,
+ // Credential: &syscall.Credential{Uid: 0, Gid 0},
+ // UidMappings: []syscall.SysProcIDMap {
+ // {ContainerID: 0, HostID: os.Getpid(), Size: 1}
+ // },
+ // GidMappings: []syscall.SysProcIDMap {
+ // {ContainerID: 0, HostID: os.Getpid(), Size: 1}
+ // },
}
cmd.Run()
@@ -39,6 +52,7 @@ func run() {
func child() {
fmt.Printf("Running inside container %v\n", os.Args[2:])
+ cgroup()
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
@@ -54,6 +68,22 @@ func child() {
must(syscall.Unmount("mytemp", 0))
}
+func cgroup() {
+ cgroups := "/sys/fs/cgroup"
+
+ mem := filepath.Join(cgroups, "memory")
+ myCgroup := filepath.Join(filepath.Join(mem, "sean"))
+ os.Mkdir(myCgroup, 0755)
+
+ must(ioutil.WriteFile(filepath.Join(myCgroup, "memory.limit_in_bytes"), []byte("999424"), 0700))
+ must(ioutil.WriteFile(filepath.Join(myCgroup, "memory.memsw.limit_in_bytes"), []byte("999424"), 0700))
+ must(ioutil.WriteFile(filepath.Join(myCgroup, "notify_on_release"), []byte("1"), 0700))
+
+ pid := strconv.Itoa(os.Getpid())
+ must(ioutil.WriteFile(filepath.Join(myCgroup, "cgroup.procs"), []byte(pid), 0700))
+
+}
+
func must(err error) {
if err != nil {
panic(err)
diff --git a/syscall/container/memorykiller/main.go b/syscall/container/memorykiller/main.go
new file mode 100644
index 0000000..8a9674c
--- /dev/null
+++ b/syscall/container/memorykiller/main.go
@@ -0,0 +1,16 @@
+package main
+
+import "fmt"
+
+const kb = 1 << 20
+
+func main() {
+ var b [][]byte
+
+ for i := 0; i < 1000; i++ {
+ var k [kb]byte
+ b = append(b, k[:])
+ fmt.Printf("allocate %d kb\n", i+1)
+ }
+
+}