cpu、内存、进程

top
ps -aux

硬盘

df -h
du -h --max-depth
lsblk
snmpwalk

网络

ip查询

mtr

mtr xxx.com :用来检测发出数据包的主机到目标主机之间经过的网关数量,及网络质量、丢包、延时.主要看loss值,只有在目标那一跳丢包才是真的丢包,中间有丢包很正常不用管(首选)

ping

ping xxxx.com :探测到对端网络质量有无丢包,可以获取域名解析的 IP 地址

traceroute

traceroute :用来检测发出数据包的主机到目标主机之间经过的网关数量,及网络质量

traceroute -n xxx.cn
traceroute -n -T -p [$Port] [$Host]
traceroute -n -T -p 443 xxx.com (探测端口)

  • -n:直接使用IP地址而非主机名称(禁用DNS反查)。
  • -T:通过TCP探测。
  • -p:设置探测的端口号。
  • [$Port]:需要探测的端口号,比如"80"。
  • [$Host]:需要探测的目标服务器地址,比如“10.10.1.1”。

curl

请求耗时长可以使用此工具判断一个请求每个歩聚的时间


curl -so /dev/null -w '   
namelookup: %{time_namelookup}
connect: %{time_connect}
appconnect: %{time_appconnect}
pretransfer: %{time_pretransfer}
redirect: %{time_redirect}
starttransfer: %{time_starttransfer}
-------
total: %{time_total}
' baidu.com -d 'a=b'

   namelookup: 0.004 //dns解析
      connect: 0.036 //建立链接时间
   appconnect: 0.000 //ssl建立时间
  pretransfer: 0.036 //准备传输时间
     redirect: 0.000 //重定向时间
starttransfer: 0.070 //传输时间
               -------
        total: 0.070  //共计

tcpdump

https://blog.csdn.net/qq_51574197/article/details/116171604

嗅探80端口

日志

dmesg
journalctl
/var/log/

给别组配了几台机子,弄了下ssh免密,结果过几天他们瞎折腾给折腾坏了,配了密钥但是ssh还是要输入密码才给登录,于是乎帮忙检查

  1. 检查sshd端口和服务
  2. 检查密钥文件以及目录,以及他们所在的位置
  3. 检查.ssh及.ssh/*的权限是否为700,600
  4. 检查.ssh及.ssh/*的属主是否是对应的用户

弄完以后才想起,这事好像不归我管......


gin

https://www.cnblogs.com/jakelin/p/15604267.html
https://gin-gonic.com/zh-cn/docs/quickstart/

https://pkg.go.dev/github.com/gin-gonic/[email protected]#RouterGroup.StaticFile
可能会涉及到的其他包:
net/http
os
render(内置了
binding(内置了

解决gin无法安装问题

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct

# 生成 mod 文件(切换到模块根目录)
go mod init modulename

# 清理无效依赖,增加缺失依赖
go mod tidy

go get -u github.com/gin-gonic/gin 

简单案例

第一个程序

package main

import (
    //"fmt"
    "net/http"
    "os"

    "github.com/gin-gonic/gin"
)

func main(){
    engine := gin.Default() //生成一个实例
    engine.GET("ping",func(c *gin.Context) {
        c.String(http.StatusOK,"pong") //申明一个路由,告诉gin触发的url和要显示的信息
    })
    engine.Run(port()) //运行
}

func port() string{
    port := os.Getenv("PORT") //获取名为PORT的参数
    if len(port) == 0 {
        port = "8080"
    }
    return ":" + port
}

运行这个程序,会看到程序监听在8080端口,我们用浏览器去访问8080

我们再尝试访问我们设置的ping,可以看到回复了一个我们设置的pong

avatar

加一点小细节

package main

import (
    "net/http"
    "os"

    "github.com/gin-gonic/gin"
)

func port() string {
    port := os.Getenv("PORT")
    if len(port) == 0 {
        port = "8080"
    }
    return ":" + port
}

type Book struct {
    Title  string `json:"书名"`
    Author string `json:"作者"`
    Date   string `json:"出版日期,omitempty"`
    ISBN   string `json:"isbn"`
}

var Booklist = map[string]Book{
    "1101100011": {Title: "go语言圣经", Author: "Alan A. A. Donovan, Brian W. Kernighan", Date: "2016-03", ISBN: "1101100011"},
    "1145141919": {Title: "U.N", Author: "anyone", ISBN: "1145141919"},
}

func AllBooks() []Book { //把booklist从map转为切片输出
    value := make([]Book, len(Booklist))
    inx := 0
    for _, book := range Booklist {
        value[inx] = book
        inx++
    }
    return value
}

func Getbook(isbn string) (Book, bool) {
    book, isfound := Booklist[isbn]
    return book, isfound
}

func Update(isbn string, book Book) bool { //如果这本书存在,那么更新
    _, exist := Booklist[isbn]
    if exist {
        Booklist[isbn] = book
    }
    return exist
}

func Create(book Book) (string, bool) { //创建书本
    _, exist := Booklist[book.ISBN]
    if exist {
        return "", false
    } else {
        Booklist[book.ISBN] = book
        return book.ISBN, true
    }
}

func Delete(isbn string) bool {
    _, exist := Booklist[isbn]
    if exist {
        delete(Booklist, isbn)
        return true
    } else {
        return false
    }
}

func main() {
    engine := gin.Default()
    engine.GET("/ping", func(c *gin.Context) {
        c.String(http.StatusOK, "pong")
    })

    engine.GET("hello", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"message": "hello gin!"}) //type H map[string]any
    })

    engine.LoadHTMLGlob("./*.html")            //加载并渲染html,另外有个类似的 LoadHTMLFiles ,但是需要一个个列举文件
    engine.StaticFile("/ico", "./favicon.ico") //将某个文件作为静态资源访问

    engine.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.html", gin.H{"title": "here is the main website!"}) //type H map[string]any
    })

    engine.GET("/api/books", func(c *gin.Context) { //以json格式打印所有的书
        c.JSON(http.StatusOK, AllBooks())
    })

    engine.GET(("/api/books/:isbn"), func(c *gin.Context) { //通过isbn查找书
        isbn := c.Params.ByName("isbn") //byname会返回匹配name的第一个参数的值,如果没有那就返回空字符串
           //isbn := c.Query("isbn")  //也可以使用c.Query(),用?传参,但是注意路由部分不能和其他的重复
        book, found := Getbook(isbn)
        if found {
            c.JSON(http.StatusOK, book)
        }
    })

    engine.PUT("/api/books/:isbn", func(c *gin.Context) { //如果存在,那么更新
        isbn := c.Params.ByName("isbn")
        var book Book
        if c.BindJSON(&book) == nil { //bind系列方法的目的是自动提取HTTP请求中的各种参数到结构体中,内部调用ShouldBindWith和MustBind,如果发生错误会400返回
            exist := Update(isbn, book)
            if exist {
                c.Status(http.StatusOK)
            } else {
                c.Status(http.StatusNotFound)
            }
        }
    })

    engine.POST("/api/books", func(c *gin.Context) { //上传书本
        var book Book
        if c.BindJSON(&book) == nil {
            isbn, ok := Create(book)
            if ok {
                c.Header("new-book's-location", "/api/books/"+isbn)
                c.Status(http.StatusCreated)
            } else {
                c.Status(http.StatusConflict)
            }
        }
    })

    engine.DELETE("/api/books/:isbn", func(c *gin.Context) {
        isbn := c.Params.ByName("isbn")
        status := Delete(isbn)
        if status {
            c.Status(http.StatusOK)
        } else {
            c.Status(http.StatusNotFound)
        }
    })

    engine.Run(port())
}
/*
[GIN-debug] GET    /                         --> main.main.func3 (3 handlers)
[GIN-debug] GET    /api/books                --> main.main.func4 (3 handlers)
[GIN-debug] GET    /api/books/:isbn          --> main.main.func5 (3 handlers)
[GIN-debug] PUT    /api/books/:isbn          --> main.main.func6 (3 handlers)
[GIN-debug] POST   /api/books                --> main.main.func7 (3 handlers)
[GIN-debug] DELETE /api/books/:isbn          --> main.main.func8 (3 handlers)
*/
//当然,这样写十分不安全,只有在这个练习题里面才能这么干,生产环境这么写黑客们就要笑嘻了

使用postman来测试这个api是否正常

GET获取书籍列表


通过isbn找书


通过isbn更新书本信息,要注意这里使用json格式的话得用编码后的字段


上传书本信息


删除书本
![

在docker上部署微服务

FROM golang:latest #表明使用的底层镜像
#RUN apt update && apt install git #pull下来的镜像有git就不用装
#RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.io,direct && go env -w GOSUMDB=off && go install github.com/gin-gonic/[email protected] && mkdir /go/src/mircoservice-1 2> /dev/null
RUN go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.io,direct && go env -w GOSUMDB=off && mkdir /go/src/mircoservice-1 && cd /go/src/mircoservice-1 && git clone https://github.com/gin-gonic/gin.git && go mod init &&  go mod tidy && go get -u github.com/gin-gonic/gin
ENV SOURCES /go/src/mircoservice-1/
COPY . ${SOURCES}
RUN cd ${SOURCES} && CGO_ENABLED=0 go build ./example.go
WORKDIR ${SOURCES}
CMD ${SOURCES}example
EXPOSE 8080 #这只是一个声明,没有实际的端口映射作用

go get 国内即使设置了代理网也很差,可能得多试几次才能成功,如果换成go install会因为包不是main而编译失败退出导致镜像构建失败

[root@iZbp15ywdll3dqiq4ija6lZ go-example]# docker run -it -d -p 8080:8080 go-service:v3 
7b1e634789394d0118b1d1222bae95de4e21f1ff6d2aeb23746cde0560a948e3
[root@iZbp15ywdll3dqiq4ija6lZ go-example]# curl 127.0.0.1:8080
<h1>hello!</h1></br>
<h2>here is the main website!</h2>
<b>enjoy your day!</b></br>[root@iZbp15ywdll3dqiq4ija6lZ go-example]# 

type关键字可以用于定义任何自定义类型,比如常见的

type st1 struct{
}
type ani int

也可以用来起别名

type intalias int // intalias类型是int类型的别名

type func



讲typefunc讲的非常好的一片博客

type myFunc func(int) int的意思是,定义一个叫做myFunc的函数类型,他的格式是func(int) int,只要输入输出符合这个格式的函数,都能强制类型转换成myFunc类,如

type myFunc func(int) int
 
 
func sum10(num int) int {
    fmt.Println(num*10)
}
 
 
func main() {
    newFunc := myFunc(sum10) // 这里把sum10强制类型转换为myFunc
}

这个别名的方式可以帮助我们方便的使用接口和重载,如下

type sumable interface {  //定义了一个叫做sumable的接口,拥有sum方法
    sum(int, int) int
}
 
// myFunc继承sumable接口
type myFunc func(int) int  //定义了一个叫做myFunc的函数类型,格式为func(int) int
 
func (f myFunc) sum (a, b int) int {  //给myFunc类型增加sum实现方法,只要是myFunc类都能调用这个方法
    res := a + b
    return f(res) //这里返回f(res),即myFunc(res),也就是调用下面被强制转换成myFunc的那些函数自己本身
}
 
func sum10(num int) int {  //定义了两个函数,类型都是func(int) int,符合myFunc,可以被强制类型转换
    return num * 10
}
 
func sum100(num int) int {
    return num * 100
}
 
// icansum结构体继承sumable接口
type icansum struct {  //定义了一个叫做icansum的结构类型
    name string
    res int
}
 
func (ics *icansum) sum(a, b int) int { //给icansum结构类型添加了sum方法
    ics.res = a + b
    return ics.res
}
 
// handler只要是继承了sumable接口的任何变量都行,我只需要你提供sum函数就好
func handlerSum(handler sumable, a, b int) int {  //定义了一个handlerSum,传入了一个sumable,只要这个实例实现了sum方法就能被调用
    res := handler.sum(a, b) //调用这个实例的sum方法
    fmt.Println(res)
    return res
}
 
func main() {
    newFunc1 := myFunc(sum10) //先把sum10类型转换为myFunc,然后赋值给newFunc1
    newFunc2 := myFunc(sum100)
 
    handlerSum(newFunc1, 1, 1)    // 20 调用newFunc1的sum方法,即第八行,先a+b=2,然后再newFunc1(2),即sum10(2)
    handlerSum(newFunc2, 1, 1)    // 200
 
    ics := &icansum{"I can sum", 0} //实例化一个icansum
    handlerSum(ics, 1, 1)         // 2  调用icansum的sum方法,即27行的函数,a+b=2
}

JSON是一种受到广泛支持的语言格式,JSON里一个对象是一个字符串到值的映射,用花括号和逗号分隔,JSON在go里面可以被用来编写map和结构体,譬如

type Movie struct {
    Title  string
    Year   int  `json:"released"` //编码后名称变为released,不加默认用成员名
    Color  bool `json:"color,omitempty"`//编码后改名外加如果是空的那么不显示
    Actors []string
}

var movies = []Movie{
    {Title: "Casablanca", Year: 1942, Color: false,
        Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}},
    {Title: "Cool Hand Luke", Year: 1967, Color: true,
        Actors: []string{"Paul Newman"}},
    {Title: "Bullitt", Year: 1968, Color: true,
        Actors: []string{"Steve McQueen", "Jacqueline Bisset"}},
    // ...
}

使用json.Marshal和json.MarshalIndent,前者返回一个slice,没有缩进,后者带两个参数,可以控制每一行的输出的前缀和每一段的缩进

data, err := json.MarshalIndent(movies, "", "    ")
if err != nil {
    log.Fatalf("JSON marshaling failed: %s", err)
}
fmt.Printf("%s\n", data)

输出

[
    {
        "Title": "Casablanca",
        "released": 1942,
        "Actors": [
            "Humphrey Bogart",
            "Ingrid Bergman"
        ]
    },
    {
        "Title": "Cool Hand Luke",
        "released": 1967,
        "color": true,
        "Actors": [
            "Paul Newman"
        ]
    },
    {
        "Title": "Bullitt",
        "released": 1968,
        "color": true,
        "Actors": [
            "Steve McQueen",
            "Jacqueline Bisset"
        ]
    }
]

解码使用unmarshaling解码成切片,可以选择性解码,即只解出需要的值

var titles []struct{ Title string }
if err := json.Unmarshal(data, &titles); err != nil {
    log.Fatalf("JSON unmarshaling failed: %s", err)
}
fmt.Println(titles) // "[{Casablanca} {Cool Hand Luke} {Bullitt}]"