tonglin0325的个人主页

go学习笔记——casbin权限管理

1.casbin简介

casbin是一个可用于Golang, Java, C/C++, Node.js, Javascript, PHP, Laravel, Python, .NET (C#), Delphi, Rust, Ruby, Lua (OpenResty), Dart (Flutter)和Elixir的授权库。

在golang web中可以使用casbin实现RBAC权限管理,类似java spring security。

官网:https://casbin.org/zh/

casbin支持多种访问模型,如ACL, RBAC, ABAC等,访问控制模型是基于PERM元模型 (Policy, Effect, Request, Matchers) 压缩而成的一个CONF文件。

casbin还支持多种策略存储方式,比如文件,MySQL、Postgres、Oracle到MongoDB、Redis、Cassandra、AWS S3等数十种数据库。参考:https://casbin.org/zh/docs/adapters/

casbin还可以通过middleware和多种语言的web框架进行集成,比如golang的Gin,Kratos等。参考:https://casbin.org/zh/docs/middlewares

2.casbin和kratos集成

可以参考kratos的example中的casbin项目:https://github.com/go-kratos/examples/tree/main/casbin

在这个例子中,作者定义了3种角色,分别具有不同的权限

  • admin:管理员角色,具有所有权限,显示所有标签页
  • moderator:普通用户角色,具有部分权限,无权限访问User标签页,无法看到Admin标签页
  • user:普通用户角色,具有一些权限,无权限访问User标签页,无法看到Admin和Moderator标签页

admin用户

moderator用户

user用户

在authz_model.conf文件中定义了访问控制模型,在authz_policy.csv中存储了权限策略

authz_model.conf文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
; m = g(r.sub, p.sub) && r.obj == p.obj && (r.act == p.act || p.act == "*")
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

  • **[request_definition]**:
      - 定义了请求的结构,即请求包含的参数。 - 这里的 `r = sub, obj, act` 表示请求由三个要素组成:`sub`(主体,例如用户或角色)、`obj`(访问的对象,例如资源或 URL)、和 `act`(操作,例如读、写)。

      **[policy_definition]**:

      • 定义了权限策略的结构,表示策略包含的参数。
      • p = sub, obj, act 表示策略同样包含主体、对象和操作三部分。每条策略通过匹配这些属性来决定权限。

      **[role_definition]**:

      • 定义了角色的继承关系,用于角色访问控制(RBAC)。
      • g = _, _ 表示使用角色继承的关系。例如,g(alice, admin) 表示用户 aliceadmin 角色的成员,继承该角色的权限。

      **[policy_effect]**:

      • 定义策略的效果,说明在多条策略匹配时如何处理。
      • e = some(where (p.eft == allow)) 表示当某条策略生效(即 p.eft 等于 allow)时,允许请求通过。some(where (...)) 的语法意味着只要有一条策略允许访问即可。

      **[matchers]**:

      • 定义了请求和策略如何匹配,以生成访问决策。
      • `m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")` 规则的含义:
        • g(r.sub, p.sub):检查请求的主体 r.sub 是否具有策略中的角色 p.sub
        • keyMatch(r.obj, p.obj):支持 URL 模式匹配(如路径前缀匹配),判断请求对象 r.obj 是否匹配策略中的对象 p.obj
        • (r.act == p.act || p.act == "*"):检查请求的操作 r.act 是否与策略中的操作 p.act 相符,或者策略允许任意操作(`p.act == “*”)。

        authz_policy.csv文件如下

        1
        2
        3
        4
        p, moderator, /admin.v1.AdminService/GetModeratorBoard, *
        p, api_admin, /admin.v1.AdminService/*, *
        g, admin, api_admin

      • **`p, moderator, /admin.v1.AdminService/GetModeratorBoard, *`**
          1. 这是一个权限策略 (`p`)。 1. `moderator` 角色可以访问 `/admin.v1.AdminService/GetModeratorBoard` 路径。 1. 最后一个参数是 `*`,表示对该路径上的任意操作(如 GET、POST 等)都允许。
      • **`p, api_admin, /admin.v1.AdminService/*, *`**
          1. 另一个权限策略 (`p`)。 1. `api_admin` 角色可以访问 `/admin.v1.AdminService/` 下的所有路径(使用了通配符 `*`)。 1. 同样,`*` 表示允许对这些路径上的所有操作。
      • **`g, admin, api_admin`**
          1. 这是一个角色继承关系 (`g`)。 1. `admin` 角色继承了 `api_admin` 角色的权限,因此拥有 `api_admin` 角色所允许的所有权限。
        • 另一个权限策略 (p)。
        • api_admin 角色可以访问 /admin.v1.AdminService/ 下的所有路径(使用了通配符 *)。
        • 同样,* 表示允许对这些路径上的所有操作。

        参考:Go 每日一库之 casbin 以及 golang微服务框架Kratos实现鉴权 - Casbin

        可以尝试启动这个casbin项目,体会一下

        项目需要依赖Consul和Jaeger

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        docker pull bitnami/consul:latest

        docker run -itd \
        --name consul-server-standalone \
        -p 8300:8300 \
        -p 8500:8500 \
        -p 8600:8600/udp \
        -e CONSUL_BIND_INTERFACE='eth0' \
        -e CONSUL_AGENT_MODE=server \
        -e CONSUL_ENABLE_UI=true \
        -e CONSUL_BOOTSTRAP_EXPECT=1 \
        -e CONSUL_CLIENT_LAN_ADDRESS=0.0.0.0 \
        bitnami/consul:latest

        docker pull jaegertracing/all-in-one:latest

        docker run -d \
        --name jaeger \
        -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
        -p 5775:5775/udp \
        -p 6831:6831/udp \
        -p 6832:6832/udp \
        -p 5778:5778 \
        -p 16686:16686 \
        -p 14268:14268 \
        -p 14250:14250 \
        -p 9411:9411 \
        jaegertracing/all-in-one:latest

        启动后端,配置如下

        访问swagger-ui:http://localhost:8800/q/swagger-ui

        启动前端

        1
        2
        yarn start

        访问前端界面:http://localhost:8081

        casbin提供多种不同的适配器,支持从配置文件,MySQL存储加载和存储策略规则。

        casbin在很多语言中都有支持的middleware中间件用于提供casbin的鉴权功能。

        比如 https://github.com/go-kratos/examples/blob/main/casbin/app/admin/internal/server/http.go 中使用的就是 tx7do/kratos-casbin 中间件来实现的casbin鉴权,代码如下

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        // NewMiddleware 创建中间件
        func NewMiddleware(ac *conf.Auth, logger log.Logger) http.ServerOption {
        m, _ := model.NewModelFromFile("/Users/lintong/coding/go/examples/casbin/app/admin/configs/authz/authz_model.conf")
        a := fileAdapter.NewAdapter("/Users/lintong/coding/go/examples/casbin/app/admin/configs/authz/authz_policy.csv")

        return http.Middleware(
        recovery.Recovery(),
        tracing.Server(),
        logging.Server(logger),
        selector.Server(
        jwt.Server(
        func(token *jwtV4.Token) (interface{}, error) {
        return []byte(ac.ApiKey), nil
        },
        jwt.WithSigningMethod(jwtV4.SigningMethodHS256),
        ),
        casbinM.Server(
        casbinM.WithCasbinModel(m),
        casbinM.WithCasbinPolicy(a),
        casbinM.WithSecurityUserCreator(myAuthz.NewSecurityUser),
        ),
        ).
        Match(NewWhiteListMatcher()).Build(),
        )
        }

        而 SecurityUser 于创建Jwt的令牌,以及后面Casbin解析和存取权鉴相关的数据,需要实现其如下方法

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        type SecurityUser interface {
        // ParseFromContext parses the user from the context.
        ParseFromContext(ctx context.Context) error

        // GetSubject returns the subject of the token.
        GetSubject() string

        // GetObject returns the object of the token.
        GetObject() string

        // GetAction returns the action of the token.
        GetAction() string
        // GetDomain returns the domain of the token.
        GetDomain() string
        }

        代码如下

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        package authz

        import (
        "context"
        "errors"
        "fmt"

        "github.com/go-kratos/kratos/v2/middleware/auth/jwt"
        "github.com/go-kratos/kratos/v2/transport"
        jwtV4 "github.com/golang-jwt/jwt/v4"
        authzM "github.com/tx7do/kratos-casbin/authz"
        )

        const (
        ClaimAuthorityId = "authorityId"
        )

        type SecurityUser struct {
        Path string
        Method string
        AuthorityId string
        Domain string
        }

        func NewSecurityUser() authzM.SecurityUser {
        return &SecurityUser{}
        }

        func (su *SecurityUser) ParseFromContext(ctx context.Context) error {
        if claims, ok := jwt.FromContext(ctx); ok {
        su.AuthorityId = claims.(jwtV4.MapClaims)[ClaimAuthorityId].(string)
        } else {
        return errors.New("jwt claim missing")
        }

        if header, ok := transport.FromServerContext(ctx); ok {
        su.Path = header.Operation()
        su.Method = "*"
        } else {
        return errors.New("jwt claim missing")
        }

        return nil
        }

        func (su *SecurityUser) GetSubject() string {
        return su.AuthorityId
        }

        func (su *SecurityUser) GetObject() string {
        return su.Path
        }

        func (su *SecurityUser) GetAction() string {
        return su.Method
        }

        func (su *SecurityUser) GetDomain() string {
        return su.Domain
        }

        参考:https://tx7do.github.io/docs/kratos_auth_authz.html

        3.casbin和gin集成

        1.basic auth+casbin

        下面举一个gin框架集成basic auth和casbin框架的例子

        basic auth集成参考:https://gin-gonic.com/docs/examples/using-basicauth-middleware/

        首先添加一个basic auth的middleware

        1
        2
        3
        4
        5
        6
        7
        8
        9
        // basic auth
        authMiddleware := gin.BasicAuth(gin.Accounts{
        "foo": "bar", //用户名:密码
        "austin": "1234",
        "lena": "hello2",
        "admin": "admin",
        })
        authGroup := r.Group("/api/v1", authMiddleware)

        再基于basic auth添加casbin,参考:https://github.com/gin-contrib/authz

        1
        2
        go get github.com/gin-contrib/authz

        注意这个库需要基于basic auth

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        func NewEnforcer() (*casbin.Enforcer, error) {
        enforcer, err := casbin.NewEnforcer("./conf/authz_model.conf", "./conf/authz_policy.csv")
        if err != nil {
        panic(err)
        }
        return enforcer, nil
        }

        // casbin
        enforcer, err := auth.NewEnforcer()
        if err != nil {
        panic(err)
        }
        authGroup.Use(authz.NewAuthorizer(enforcer))

        // handler
        UserRouters(userHandler, authGroup)

        其中userHandler中有如下接口用于获取user

        1
        2
        /api/v1/user/{id}

        authz_model.conf访问控制模型配置文件,其中keyMatch用于匹配/api/v1/user/*的path,参考:https://casbin.org/docs/function/

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        [request_definition]
        r = sub, obj, act

        [policy_definition]
        p = sub, obj, act

        [role_definition]
        g = _, _

        [policy_effect]
        e = some(where (p.eft == allow))

        [matchers]
        m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

        authz_policy.csv权限策略文件

        1
        2
        3
        4
        5
        6
        p, admin, /api/v1/user/*, *
        p, admin, /api/v1/user, POST
        p, foo, /api/v1/user/1, GET
        p, austin, /api/v1/user, POST
        p, lena, /api/v1/user, PUT

        admin用户拥有创建user的权限

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        curl -i 'http://localhost:18080/api/v1/user' \
        --header 'Content-Type: application/json' \
        --header 'Authorization: Basic YWRtaW46YWRtaW4=' \
        --data-raw '{
        "username": "test",
        "email":"test@test"
        }'
        HTTP/1.1 200 OK
        Content-Type: application/json; charset=utf-8
        Date: Sat, 23 Nov 2024 15:48:38 GMT
        Content-Length: 98

        {"code":200,"msg":"create user success","data":{"id":10025,"username":"test","email":"test@test"}}%

        foo用户只有访问id=1的用户的权限,访问id=2会返回403

        1
        2
        3
        4
        5
        6
        7
        curl -I -X GET 'http://localhost:18080/api/v1/user/2' \
        --header 'Authorization: Basic Zm9vOmJhcg==' \
        --header 'Content-Type: application/json'
        HTTP/1.1 403 Forbidden
        Date: Sun, 17 Nov 2024 16:21:01 GMT
        Content-Length: 0

        2.使用GORM adapter

        如果使用MySQL存储policy的话,可以使用**gorm-adapter**,参考:https://casbin.org/zh/docs/adapters/ 以及 https://dev.to/maxwellhertz/tutorial-integrate-gin-with-cabsin-56m0

        1
        2
        go get github.com/casbin/gorm-adapter/v3

        并在enforce中从csv文件的权限策略适配器,修改成gorm的适配器

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        func NewEnforcer(adapter *gormadapter.Adapter) (*casbin.Enforcer, error) {
        //enforcer, err := casbin.NewEnforcer("./conf/authz_model.conf", "./conf/authz_policy.csv")
        enforcer, err := casbin.NewEnforcer("./conf/authz_model.conf", adapter)
        if err != nil {
        panic(err)
        }
        return enforcer, nil
        }

        func NewGormAdapter(conf *viper.Viper) (*gormadapter.Adapter, error) {
        dsn := conf.GetString("db.mysql.dsn")
        print(dsn)
        adapter, err := gormadapter.NewAdapter("mysql", dsn, true)
        if err != nil {
        panic(err)
        }
        return adapter, nil
        }

        运行代码后,会自动在MySQL数据库中创建一张名为casbin_rule的表,如下

        表定义应为(id int primary key, ptype varchar, v0 varchar, v1 varchar, v2 varchar, v3 varchar, v4 varchar, v5 varchar)。

        唯一键索引应在ptype,v0,v1,v2,v3,v4,v5列上建立。

        使用如下代码可以添加policy

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        package auth

        import (
        "fmt"
        "gin-template/internal/config"
        zaplog "gin-template/internal/logger"
        "github.com/spf13/viper"
        "go.uber.org/zap"
        "testing"
        )

        var (
        conf *viper.Viper
        zap_logger *zap.Logger
        )

        func init() {
        conf = config.InitConfig()
        zap_logger = zaplog.InitLogger(conf)
        }

        func TestNewGormAdapter(t *testing.T) {
        adapter, err := NewGormAdapter(conf)
        if err != nil {
        fmt.Println(err)
        return
        }
        enforcer, err := NewEnforcer(adapter)
        if err != nil {
        fmt.Println(err)
        return
        }
        _, err = enforcer.AddPolicy("jack", "data1", "write")
        if err != nil {
        fmt.Println(err)
        return
        }
        _, err = enforcer.AddPolicy("jack", "data2", "write")
        if err != nil {
        fmt.Println(err)
        return
        }
        }

        参考:https://github.com/casbin/gorm-adapter

        如果要移除policy

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        // 删除policy
        _, err = enforcer.RemovePolicy("jack", "data3", "write")
        if err != nil {
        fmt.Println(err)
        return
        }
        // 删除index=0位置的值等于jack的policy
        _, err = enforcer.RemoveFilteredPolicy(0, "jack")
        if err != nil {
        fmt.Println(err)
        return
        }

        3.刷新权限policy

        当权限policy变更了之后,为了保证鉴权结果的正确,需要即使加载最新的权限policy,方法有如下几种

        1.定时任务调用 LoadPolicy 方法

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        // 开启定时自动加载策略
        go func() {
        ticker := time.NewTicker(10 * time.Second) // 每隔 10 秒加载一次
        defer ticker.Stop()
        for range ticker.C {
        err := enforcer.LoadPolicy()
        if err != nil {
        // 记录错误日志
        fmt.Println("Failed to load policy:", err.Error())
        } else {
        fmt.Println("Policy reloaded successfully.")
        }
        }
        }()

        2.手动调用 LoadPolicy 方法

        ``在要鉴权之前,调用如下代码

        1
        2
        enforcer.LoadPolicy()

        3.使用 Watcher 机制

        可以使用watcher来通知每个实例的enforcer更新权限策略,参考:https://casbin.org/docs/watchers/

        这里以 https://github.com/casbin/redis-watcher 为例,使用这个redis-watcher需要依赖golang redis v9

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        // casbin watcher
        watcher, _ := rediswatcher.NewWatcher("localhost:3306", rediswatcher.WatcherOptions{
        Options: redis.Options{
        Network: "tcp",
        Password: "",
        },
        Channel: "/casbin",
        // Only exists in test, generally be true
        IgnoreSelf: false,
        })
        err := enforcer.SetWatcher(watcher)
        if err != nil {
        zap.L().Error(err.Error())
        }
        err = watcher.SetUpdateCallback(func(msg string) {
        println(msg)
        enforcer.LoadPolicy()
        })
        if err != nil {
        zap.L().Error(err.Error())
        }

        其中updateCallback是回调函数,这里打印一下权限变更的msg

        写一个测试用例添加一下policy,这里也设置了watcher,会将权限变更的信息写到redis中

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        func TestNewGormAdapter(t *testing.T) {
        adapter, err := NewGormAdapter(conf)
        if err != nil {
        fmt.Println(err)
        return
        }
        enforcer, err := NewEnforcer(adapter)
        if err != nil {
        fmt.Println(err)
        return
        }
        watcher, _ := rediswatcher.NewWatcher("localhost:3306", rediswatcher.WatcherOptions{
        Options: redis.Options{
        Network: "tcp",
        Password: "",
        },
        Channel: "/casbin",
        // Only exists in test, generally be true
        IgnoreSelf: false,
        })
        err = enforcer.SetWatcher(watcher)

        if err != nil {
        zap.L().Error(err.Error())
        }
        _, err = enforcer.AddPolicy("jack", "data1", "write")
        if err != nil {
        fmt.Println(err)
        return
        }
        _, err = enforcer.AddPolicy("jack", "data2", "write")
        if err != nil {
        fmt.Println(err)
        return
        }
        }

        查看原先的日志,获取到2次policy变更的消息

        1
        2
        3
        {"Method":"UpdateForAddPolicy","ID":"a14b5075-bd4c-43fa-b987-8e500d9fcf46","Sec":"p","Ptype":"p","OldRule":null,"OldRules":null,"NewRule":["jack","data1","write"],"NewRules":null,"FieldIndex":0,"FieldValues":null}
        {"Method":"UpdateForAddPolicy","ID":"a14b5075-bd4c-43fa-b987-8e500d9fcf46","Sec":"p","Ptype":"p","OldRule":null,"OldRules":null,"NewRule":["jack","data2","write"],"NewRules":null,"FieldIndex":0,"FieldValues":null}

        全文 >>

  • Ubuntu下Ansible安装和使用

    Ansible是一个批量部署的工具

    参考:Ansible中文权威指南

    1.安装

    1
    2
    3
    4
    5
    sudo apt-get install software-properties-common
    sudo apt-add-repository ppa:ansible/ansible
    sudo apt-get update
    sudo apt-get install ansible

    2.在/etc/ansible/hosts文件中添加服务器的ip

    1
    2
    vim /etc/ansible/hosts

    3.需要将自己机器的/.ssh/目录下公钥,即pub文件,添加到服务器的

    全文 >>

    Logstash安装和使用

    Logstash 是开源的服务器端数据处理管道,能够同时 从多个来源采集数据、转换数据,然后将数据发送到您最喜欢的 “存储库” 中。(我们的存储库当然是 Elasticsearch。)

    作用:集中、转换和存储数据

    官方网站:

    1
    2
    https://www.elastic.co/cn/products/logstash

    一个民间的中文Logstash最佳实践:

    1
    2
    https://doc.yonyoucloud.com/doc/logstash-best-practice-cn/index.html

    全文 >>

    使用MegaCli监控Linux硬盘

    **1.**首先查看机器是否使用的是MegaRAID卡

    1
    2
    3
    dmesg | grep RAID
    [ 6.932741] scsi host0: Avago SAS based MegaRAID driver

    **2.**添加 megaraid 源:

    修改 /etc/apt/sources.list 在末尾添加

    1
    2
    deb http://hwraid.le-vert.net/ubuntu precise main

    然后执行:

    1
    2
    3
    apt-get update
    apt-get install megacli megactl megaraid-status

    如果执行提示 GPG 错误,需要执行如下命令添加证书:

    1
    2
    wget -O - http://hwraid.le-vert.net/debian/hwraid.le-vert.net.gpg.key | sudo apt-key add -

    然后再次执行:

    1
    2
    apt-get install megacli megactl megaraid-status

    **3.**使用megacli命令进行一些简单的查询

    显示所有RAID级别、设置及逻辑盘信息

    1
    2
    sudo megacli -LDInfo -Lall -aALL 

    输出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
                                         
    Adapter 0 -- Virtual Drive Information:
    Virtual Drive: 0 (Target Id: 0)
    Name :
    RAID Level : Primary-1, Secondary-0, RAID Level Qualifier-0
    Size : 1.090 TB
    Sector Size : 512
    Is VD emulated : No
    Mirror Data : 1.090 TB
    State : Optimal
    Strip Size : 64 KB
    Number Of Drives : 2
    Span Depth : 1
    Default Cache Policy: WriteBack, ReadAhead, Direct, No Write Cache if Bad BBU
    Current Cache Policy: WriteBack, ReadAhead, Direct, No Write Cache if Bad BBU
    Default Access Policy: Read/Write
    Current Access Policy: Read/Write
    Disk Cache Policy : Disk's Default
    Encryption Type : None
    Default Power Savings Policy: Controller Defined
    Current Power Savings Policy: None
    Can spin up in 1 minute: Yes
    LD has drives that support T10 power conditions: Yes
    LD's IO profile supports MAX power savings with cached writes: No
    Bad Blocks Exist: No
    Is VD Cached: No



    Exit Code: 0x00

    显示所有的物理信息

    1
    2
    sudo megacli -PDList -aAll

    过滤输出

    1
    2
    sudo megacli -PDList -aAll  | grep "Firmware state\|Slot Number\|Error"

    全文 >>

    使用SMART监控Ubuntu

    参考:完全用 GNU/Linux 工作 - 29. 檢測硬碟 S.M.A.R.T. 健康狀態

    1.安装

    1
    2
    sudo apt-get install smartmontools

    2.查看硬盘的参数,需要获得Root权限

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    sudo smartctl -i /dev/sda

    smartctl 6.5 2016-01-24 r4214 [x86_64-linux-4.4.0-122-generic] (local build)
    Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org

    === START OF INFORMATION SECTION ===
    Model Family: Samsung based SSDs
    Device Model: Samsung SSD 850 EVO 250GB
    Serial Number: S3LCNF0J807262K
    LU WWN Device Id: 5 002538 d42253d35
    Firmware Version: EMT03B6Q
    User Capacity: 250,059,350,016 bytes [250 GB]
    Sector Size: 512 bytes logical/physical
    Rotation Rate: Solid State Device
    Form Factor: 2.5 inches
    Device is: In smartctl database [for details use: -P show]
    ATA Version is: ACS-2, ATA8-ACS T13/1699-D revision 4c
    SATA Version is: SATA 3.1, 6.0 Gb/s (current: 6.0 Gb/s)
    Local Time is: Mon May 7 10:14:29 2018 CST
    SMART support is: Available - device has SMART capability.
    SMART support is: Enabled

    3.如果使用下面的Python脚本来调用该命令的时候,是需要获得Root权限的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/usr/bin/python
    # !-*- coding:utf8 -*-

    import os


    def main():
    dir = "~/桌面/test.sh"
    result = os.system("sh ~/桌面/test.sh")
    # print result


    if __name__ == '__main__':
    main()

    可以使用下面的方法来实现免输入密码,使用 sudo visudo 命令对/etc/sudoers文件增加下面设置

    1
    2
    lintong  ALL=(ALL) NOPASSWD: /usr/sbin/smartctl

    全文 >>

    Kibana学习笔记——安装和使用

    1.首先下载Kibana

    1
    2
    https://www.elastic.co/downloads

    2.解压

    1
    2
    tar -zxvf kibana-6.2.1-linux-x86_64.tar.gz -C ~/software/

    3.修改配置,在config文件夹下面修改kibana.yml

    1
    2
    3
    4
    5
    #配置本机ip
    server.host: "127.0.0.1"
    #配置es集群url
    elasticsearch.url: "http://127.0.0.1:9200"

    4.启动

    1
    2
    ./bin/kibana

    5.访问web

    1
    2
    http://localhost:5601/app/kibana

    6.在Manager里面添加index,demo中的index名称叫做es

    添加之后

    7.在discover中可以查看数据,里面还会对top数据进行统计

    8.在Dev tool中可以进行查询

    全文 >>

    open-falcon实现邮件报警

    1.请安装好Go的环境,参考上一篇open-falcon的安装博文

    2.安装** mail-provider**

    1
    2
    https://github.com/open-falcon/mail-provider

    安装方法

    1
    2
    3
    4
    5
    6
    7
    8
    cd $GOPATH/src
    mkdir github.com/open-falcon/ -p
    cd github.com/open-falcon/
    git clone https://github.com/open-falcon/mail-provider.git
    cd mail-provider
    go get ./...
    ./control build

    全文 >>

    Ubuntu下安装open-falcon-v0.2.1

    在Ubuntu下安装open-falcon和Centos下安装的方法有点区别,因为Ubuntu使用的包管理器是apt-get,而Centos下使用的是Yum,建议不要再Ubuntu下使用yum

    建议自己下载源码打包二进制包来安装,因为官方给出的二进制包应该是再centos下打包的,再Ubuntu下运行可能会出现问题

    1.安装Go,首先去官网下载,需要fq

    1
    2
    https://golang.org

    顺便安装Goland,注册服务器 http://idea.youbbs.org

    2.在/etc/profile中添加,后source /etc/profile

    1
    2
    3
    4
    5
    #Go
    export GOROOT=/home/lintong/software/go
    export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
    export GOPATH=/home/lintong/software/gopath

    验证是否安装成功

    1
    2
    3
    go version
    go version go1.10.2 linux/amd64

    接下来参考

    Ubuntu 16.04 部署 open-falcon

    运维监控系统之Open-Falcon

    Open-falcon的官方README

    全文 >>