• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

chaosblade-exec-os项目的burnio.go文件解读

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

#################################################

代码位置:https://github.com/chaosblade-io/chaosblade-exec-os.git

文件位置:chaosblade-exec-os/exec/bin/burnio/burnio.go

 

这个文件刚开始读起来有点难以理解,甚至懵逼,为何呢?

比如一个可执行文件叫chaos_burnio,这个可执行文件的内容就是第二次以执行脚本的命令的方式执行相同的可执行文件,一开始不理解为何这样写,这就像套娃一样,以为这会进入到一个死循环

然后,这两次调用并不相同,主要在于参数不同,第一次调用会重新组装参数,而且会根据条件来选择执行,因此两者并不会进入死循环,不过呢,第一次看到还是感觉蛮伤脑的,这样组织代码的还是第一次见

 

# 这是第二次执行:调用可执行文件chaos_burnio,但是参数不再有--start,--stop了,总共四个分支执行,只有--start和--stop才会有第二次执行相同可执行命令,故不会在进入到死循环    

cmd := exec.CommandContext(ctx, "/bin/sh", "-c", script+" "+args)
output, err :
= cmd.CombinedOutput()

 

 

 

 

/*
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
    "context"
    "flag"
    "fmt"
    "path"
    "strings"
    "time"

    "github.com/chaosblade-io/chaosblade-spec-go/channel"
    "github.com/chaosblade-io/chaosblade-spec-go/util"

    "github.com/chaosblade-io/chaosblade-exec-os/exec"
    "github.com/chaosblade-io/chaosblade-exec-os/exec/bin"
)

const count = 100

var burnIODirectory, burnIOSize string
var burnIORead, burnIOWrite, burnIOStart, burnIOStop, burnIONohup bool

func main() {
    flag.StringVar(&burnIODirectory, "directory", "", "the directory where the disk is burning")
    flag.StringVar(&burnIOSize, "size", "", "block size")
    flag.BoolVar(&burnIOWrite, "write", false, "write io")
    flag.BoolVar(&burnIORead, "read", false, "read io")
    flag.BoolVar(&burnIOStart, "start", false, "start burn io")
    flag.BoolVar(&burnIOStop, "stop", false, "stop burn io")
    flag.BoolVar(&burnIONohup, "nohup", false, "start by nohup")
    bin.ParseFlagAndInitLog()

    if burnIOStart {
        startBurnIO(burnIODirectory, burnIOSize, burnIORead, burnIOWrite)
    } else if burnIOStop {
        stopBurnIO(burnIODirectory, burnIORead, burnIOWrite)
    } else if burnIONohup {
        if burnIORead {
            go burnRead(burnIODirectory, burnIOSize)
        }
        if burnIOWrite {
            go burnWrite(burnIODirectory, burnIOSize)
        }
        select {}
    } else {
        bin.PrintErrAndExit("less --start or --stop flag")
    }
}

var readFile = "chaos_burnio.read"
var writeFile = "chaos_burnio.write"
var burnIOBin = exec.BurnIOBin
var logFile = util.GetNohupOutput(util.Bin, "chaos_burnio.log")

var cl = channel.NewLocalChannel()

var stopBurnIOFunc = stopBurnIO

// start burn io
func startBurnIO(directory, size string, read, write bool) {
    ctx := context.Background()
    response := cl.Run(ctx, "nohup",
        fmt.Sprintf(`%s --directory %s --size %s --read=%t --write=%t --nohup=true > %s 2>&1 &`,
            path.Join(util.GetProgramPath(), burnIOBin), directory, size, read, write, logFile))
    if !response.Success {
        stopBurnIOFunc(directory, read, write)
        bin.PrintErrAndExit(response.Err)
        return
    }
    // check
    time.Sleep(time.Second)
    response = cl.Run(ctx, "grep", fmt.Sprintf("%s %s", bin.ErrPrefix, logFile))
    if response.Success {
        errMsg := strings.TrimSpace(response.Result.(string))
        if errMsg != "" {
            stopBurnIOFunc(directory, read, write)
            bin.PrintErrAndExit(errMsg)
            return
        }
    }
    bin.PrintOutputAndExit("success")
}

// stop burn io,  no need to add os.Exit
func stopBurnIO(directory string, read, write bool) {
    ctx := context.WithValue(context.Background(), channel.ExcludeProcessKey, "--stop")
    if read {
        // dd process
        pids, _ := cl.GetPidsByProcessName(readFile, ctx)
        if pids != nil && len(pids) > 0 {
            cl.Run(ctx, "kill", fmt.Sprintf("-9 %s", strings.Join(pids, " ")))
        }
        // chaos_burnio process
        ctxWithKey := context.WithValue(ctx, channel.ProcessKey, burnIOBin)
        pids, _ = cl.GetPidsByProcessName("--read=true", ctxWithKey)
        if pids != nil && len(pids) > 0 {
            cl.Run(ctx, "kill", fmt.Sprintf("-9 %s", strings.Join(pids, " ")))
        }
        cl.Run(ctx, "rm", fmt.Sprintf("-rf %s*", path.Join(directory, readFile)))
    }
    if write {
        // dd process
        pids, _ := cl.GetPidsByProcessName(writeFile, ctx)
        if pids != nil && len(pids) > 0 {
            cl.Run(ctx, "kill", fmt.Sprintf("-9 %s", strings.Join(pids, " ")))
        }
        ctxWithKey := context.WithValue(ctx, channel.ProcessKey, burnIOBin)
        pids, _ = cl.GetPidsByProcessName("--write=true", ctxWithKey)
        if pids != nil && len(pids) > 0 {
            cl.Run(ctx, "kill", fmt.Sprintf("-9 %s", strings.Join(pids, " ")))
        }
        cl.Run(ctx, "rm", fmt.Sprintf("-rf %s*", path.Join(directory, writeFile)))
    }
}

// write burn
func burnWrite(directory, size string) {
    tmpFileForWrite := path.Join(directory, writeFile)
    for {
        args := fmt.Sprintf(`if=/dev/zero of=%s bs=%sM count=%d oflag=dsync`, tmpFileForWrite, size, count)
        response := cl.Run(context.TODO(), "dd", args)
        if !response.Success {
            bin.PrintAndExitWithErrPrefix(response.Err)
            return
        }
    }
}

// read burn
func burnRead(directory, size string) {
    // create a 600M file under the directory
    tmpFileForRead := path.Join(directory, readFile)
    createArgs := fmt.Sprintf("if=/dev/zero of=%s bs=%dM count=%d oflag=dsync", tmpFileForRead, 6, count)
    response := cl.Run(context.TODO(), "dd", createArgs)
    if !response.Success {
        bin.PrintAndExitWithErrPrefix(
            fmt.Sprintf("using dd command to create a temp file under %s directory for reading error, %s",
                directory, response.Err))
    }
    for {
        args := fmt.Sprintf(`if=%s of=/dev/null bs=%sM count=%d iflag=dsync,direct,fullblock`, tmpFileForRead, size, count)
        response = cl.Run(context.TODO(), "dd", args)
        if !response.Success {
            bin.PrintAndExitWithErrPrefix(fmt.Sprintf("using dd command to burn read io error, %s", response.Err))
            return
        }
    }
}

 

 

 

 

 

 

 

 

 

 

 

##################################################


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
go-micro入门发布时间:2022-07-10
下一篇:
go http.Handler发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap