├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Makefile ├── README.md ├── build ├── image │ └── musl │ │ └── Dockerfile └── spec.go ├── common ├── constants.go ├── signal.go └── utils.go ├── controller ├── controller.go ├── create.go ├── destroy.go ├── manager.go ├── remove.go └── status.go ├── go.mod ├── go.sum ├── main.go ├── module ├── common.go ├── errorreturned.go ├── linedelayed.go ├── module.go └── variablemodified.go ├── pom.xml └── script ├── shell_break_and_return.sh ├── shell_break_and_return_attach.sh ├── shell_break_and_return_attach_parent.sh ├── shell_check_process_duplicate.sh ├── shell_check_process_id.sh ├── shell_initialization.sh ├── shell_modify_variable.sh ├── shell_modify_variable_attach.sh ├── shell_modify_variable_attach_parent.sh ├── shell_remove_process.sh ├── shell_response_delay.sh ├── shell_response_delay_attach.sh └── shell_response_delay_attach_parent.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | *.classpath 23 | *.project 24 | diamond_config_data.log 25 | diamond_config_data.log.* 26 | 27 | 28 | #ignore these files 29 | */.settings/* 30 | .settings/* 31 | */bin/* 32 | */target/* 33 | bin/* 34 | target/* 35 | **/target/** 36 | */.idea/* 37 | .idea/* 38 | *.iml 39 | */*.iml 40 | build-target 41 | # Logs and databases # 42 | ###################### 43 | *.log 44 | *.sql 45 | *.sqlite 46 | 47 | # OS generated files # 48 | ###################### 49 | .DS_Store 50 | .DS_Store? 51 | ._* 52 | .Spotlight-V100 53 | .Trashes 54 | ehthumbs.db 55 | Thumbs.db 56 | 57 | # project 58 | /plugins 59 | /cp.sh 60 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at chaosblade.io.01@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) 72 | 73 | [homepage]: https://www.contributor-covenant.org -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to chaosblade-exec-cplus 2 | 3 | Welcome to ChaosBlade world, here is a list of contributing guide for you. If you find something incorrect or missing 4 | content in the page, please submit an issue or PR to fix it. 5 | 6 | 7 | ## What can you do 8 | Every action to make project better is encouraged. On GitHub, every improvement for the project could be via a PR 9 | (short 10 | for pull request). 11 | 12 | * If you find a typo, try to fix it! 13 | * If you find a bug, try to fix it! 14 | * If you find some redundant codes, try to remove them! 15 | * If you find some test cases missing, try to add them! 16 | * If you could enhance a feature, please **DO NOT** hesitate! 17 | * If you find code implicit, try to add comments to make it clear! 18 | * If you find code ugly, try to refactor that! 19 | * If you can help to improve documents, it could not be better! 20 | * If you find document incorrect, just do it and fix that! 21 | * ... 22 | 23 | Actually it is impossible to list them completely. Just remember one principle: 24 | 25 | **WE ARE LOOKING FORWARD TO ANY PR FROM YOU.** 26 | 27 | 28 | ## Contributing 29 | ### Preparation 30 | Before you contribute, you need to register a Github ID. Prepare the following environment: 31 | * JDK 1.8+ 32 | * git 33 | 34 | ### Workflow 35 | We use the `master` branch as the development branch, which indicates that this is a unstable branch. 36 | 37 | Here are the workflow for contributors: 38 | 39 | 1. Fork to your own 40 | 2. Clone fork to local repository 41 | 3. Create a new branch and work on it 42 | 4. Keep your branch in sync 43 | 5. Commit your changes (make sure your commit message concise) 44 | 6. Push your commits to your forked repository 45 | 7. Create a pull request 46 | 47 | Please follow [the pull request template](./.github/PULL_REQUEST_TEMPLATE.md). 48 | Please make sure the PR has a corresponding issue. 49 | 50 | After creating a PR, one or more reviewers will be assigned to the pull request. 51 | The reviewers will review the code. 52 | 53 | Before merging a PR, squash any fix review feedback, typo, merged, and rebased sorts of commits. 54 | The final commit message should be clear and concise. 55 | 56 | ### Compile 57 | In the project root directory, execute the following command to compile 58 | ```bash 59 | Sh build.sh 60 | ``` 61 | 62 | The compilation result will be stored in the target directory. 63 | 64 | ### Code Style 65 | We suggest that all contributors should install [p3c](https://github.com/alibaba/p3c) plugin to unify code style and 66 | analyze code quality. 67 | 68 | ### Commit Rules 69 | #### Commit Message 70 | 71 | Commit message could help reviewers better understand what is the purpose of submitted PR. It could help accelerate the code review procedure as well. We encourage contributors to use **EXPLICIT** commit message rather than ambiguous message. In general, we advocate the following commit message type: 72 | 73 | * feat: A new feature 74 | * fix: A bug fix 75 | * docs: Documentation only changes 76 | * style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) 77 | * refactor: A code change that neither fixes a bug nor adds a feature 78 | * perf: A code change that improves performance 79 | * test: Adding missing or correcting existing tests 80 | * chore: Changes to the build process or auxiliary tools and libraries such as documentation generation 81 | 82 | On the other side, we discourage contributors from committing message like the following ways: 83 | 84 | * ~~fix bug~~ 85 | * ~~update~~ 86 | * ~~add doc~~ 87 | 88 | If you get lost, please see [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/) for a start. 89 | 90 | #### Commit Content 91 | 92 | Commit content represents all content changes included in one commit. We had better include things in one single commit which could support reviewer's complete review without any other commits' help. In another word, contents in one single commit can pass the CI to avoid code mess. In brief, there are two minor rules for us to keep in mind: 93 | 94 | * avoid very large change in a commit; 95 | * complete and reviewable for each commit. 96 | 97 | No matter commit message, or commit content, we do take more emphasis on code review. 98 | 99 | 100 | ### Pull Request 101 | We use [GitHub Issues](https://github.com/chaosblade-io/chaosblade-exec-cplus/issues) and [Pull Requests](https://github.com/chaosblade-io/chaosblade-exec-cplus/pulls) for trackers. 102 | 103 | If you find a typo in document, find a bug in code, or want new features, or want to give suggestions, 104 | you can [open an issue on GitHub](https://github.com/chaosblade-io/chaosblade-exec-cplus/issues/new) to report it. 105 | Please follow the guideline message in the issue template. 106 | 107 | If you want to contribute, please follow the [contribution workflow](#Workflow) and create a new pull request. 108 | If your PR contains large changes, e.g. component refactor or new components, please write detailed documents 109 | about its design and usage. 110 | 111 | Note that a single PR should not be too large. If heavy changes are required, it's better to separate the changes 112 | to a few individual PRs. 113 | 114 | 115 | ### Code Review 116 | All code should be well reviewed by one or more committers. Some principles: 117 | 118 | - Readability: Important code should be well-documented. Comply with our code style. 119 | - Elegance: New functions, classes or components should be well designed. 120 | - Testability: Important code should be well-tested (high unit test coverage). 121 | 122 | ## Community 123 | ### Contact Us 124 | #### Mailing list 125 | If you have any questions or advice, please contact chaosblade.io.01@gmail.com. 126 | 127 | #### DingDing 128 | You can also search the ID: `23177705` in dingding(钉钉) app to join the ChaosBlade group. 129 | 130 | 131 | ## Others 132 | ### Code of Conduct 133 | *"In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making 134 | participation in our project and our community a harassment-free experience for everyone, regardless of age, body 135 | size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, 136 | socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation..."* 137 | 138 | See details of [CONTRIBUTOR COVENANT CODE OF CONDUCT](https://github.com/chaosblade-io/chaosblade-exec-cplus/blob/master/CODE_OF_CONDUCT.md) 139 | 140 | ### Sign your work 141 | The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as an open-source patch. 142 | The rules are pretty simple: if you can certify the below (from [developercertificate.org](http://developercertificate.org/)): 143 | 144 | ``` 145 | Developer Certificate of Origin 146 | Version 1.1 147 | 148 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 149 | 660 York Street, Suite 102, 150 | San Francisco, CA 94110 USA 151 | 152 | Everyone is permitted to copy and distribute verbatim copies of this 153 | license document, but changing it is not allowed. 154 | 155 | Developer's Certificate of Origin 1.1 156 | 157 | By making a contribution to this project, I certify that: 158 | 159 | (a) The contribution was created in whole or in part by me and I 160 | have the right to submit it under the open source license 161 | indicated in the file; or 162 | 163 | (b) The contribution is based upon previous work that, to the best 164 | of my knowledge, is covered under an appropriate open source 165 | license and I have the right under that license to submit that 166 | work with modifications, whether created in whole or in part 167 | by me, under the same open source license (unless I am 168 | permitted to submit under a different license), as indicated 169 | in the file; or 170 | 171 | (c) The contribution was provided directly to me by some other 172 | person who certified (a), (b) or (c) and I have not modified 173 | it. 174 | 175 | (d) I understand and agree that this project and the contribution 176 | are public and that a record of the contribution (including all 177 | personal information I submit with it, including my sign-off) is 178 | maintained indefinitely and may be redistributed consistent with 179 | this project or the open source license(s) involved. 180 | ``` 181 | 182 | Then you just add a line to every git commit message: 183 | 184 | ``` 185 | Signed-off-by: Joe Smith 186 | ``` 187 | 188 | Use your real name (sorry, no pseudonyms or anonymous contributions.) 189 | 190 | If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with `git commit -s`. 191 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build clean 2 | 3 | BLADE_SRC_ROOT=$(shell pwd) 4 | UNAME := $(shell uname) 5 | 6 | ifeq ($(BLADE_VERSION), ) 7 | BLADE_VERSION=1.7.3 8 | endif 9 | 10 | BUILD_TARGET=build-target 11 | BUILD_TARGET_DIR_NAME=chaosblade-$(BLADE_VERSION) 12 | BUILD_TARGET_PKG_DIR=$(BUILD_TARGET)/chaosblade-$(BLADE_VERSION) 13 | BUILD_TARGET_YAML=$(BUILD_TARGET_PKG_DIR)/yaml 14 | BUILD_TARGET_CPLUS_LIB=$(BUILD_TARGET_PKG_DIR)/lib/cplus 15 | BUILD_TARGET_CPLUS_SCRIPT=$(BUILD_TARGET_CPLUS_LIB)/script 16 | # yaml file name 17 | CPLUS_YAML_FILE=$(BUILD_TARGET_YAML)/chaosblade-cplus-spec.yaml 18 | # agent file name 19 | CPLUS_AGENT_FILE_NAME=chaosblade-exec-cplus 20 | 21 | GO_ENV=CGO_ENABLED=1 22 | GO_MODULE=GO111MODULE=on 23 | GO=env $(GO_ENV) $(GO_MODULE) go 24 | ifeq ($(GOOS), linux) 25 | GO_FLAGS=-ldflags="-linkmode external -extldflags -static" 26 | endif 27 | 28 | build: pre_build build_cplus build_yaml 29 | cp -R script/* $(BUILD_TARGET_CPLUS_SCRIPT) 30 | chmod -R 755 $(BUILD_TARGET_CPLUS_LIB) 31 | 32 | pre_build: 33 | rm -rf $(BUILD_TARGET_PKG_DIR) 34 | mkdir -p $(BUILD_TARGET_YAML) $(BUILD_TARGET_CPLUS_SCRIPT) 35 | 36 | build_yaml: build/spec.go 37 | $(GO) run $< $(CPLUS_YAML_FILE) 38 | 39 | build_cplus: main.go 40 | $(GO) build $(GO_FLAGS) -o $(BUILD_TARGET_CPLUS_LIB)/chaosblade-exec-cplus $< 41 | 42 | # build chaosblade linux version by docker image 43 | build_linux: 44 | docker build -f build/image/musl/Dockerfile -t chaosblade-cplus-build-musl:latest build/image/musl 45 | docker run --rm \ 46 | -v $(shell echo -n ${GOPATH}):/go \ 47 | -v $(BLADE_SRC_ROOT):/chaosblade-exec-cplus \ 48 | -w /chaosblade-exec-cplus \ 49 | chaosblade-cplus-build-musl:latest 50 | 51 | # test 52 | test: 53 | mvn clean test -U 54 | # clean all build result 55 | clean: 56 | $(GO) clean ./... 57 | rm -rf $(BUILD_TARGET) 58 | 59 | all: build test 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo](https://chaosblade.oss-cn-hangzhou.aliyuncs.com/doc/image/chaosblade-logo.png) 2 | 3 | # Chaosblade-exec-cplus: Chaosblade executor for chaos experiments on c++ applications 4 | 5 | 6 | ## Introduction 7 | The project is a chaosblade executor based on [GDB] for chaos 8 | experiments on c++ applications. The drill can be implemented through the blade cli, see 9 | [chaosblade](https://github.com/chaosblade-io/chaosblade) project for details. 10 | 11 | 12 | ## Compiling 13 | In the project root directory, execute the following command to compile 14 | ```bash 15 | make 16 | ``` 17 | 18 | The compilation result will be stored in the target directory. 19 | 20 | 21 | ## Deploying 22 | When deploying Chaosblade-exec-cplus, the shell script files under the source’s folders [/src/main/resources/script] should be deployed on the disk of server separately. Create a new folder in server, put all the shell script files under the new folder, and when you startup chaosblade-exec-cplus jar, you can use the command just like: 23 | ```bash 24 | nohup java -jar chaosblade-exec-cplus.jar --server.port=8908 --script.location=/home/admin/cplus/ & 25 | ``` 26 | the value of parameter "script.location" can be set the location of the new created folder. So that the chaosblade-exec-cplus jar know where to get the script files. 27 | 28 | 29 | ## Restriction 30 | 1. If the C++ application doesn’t add '-g' when compiling, Chaosblade-exec-cplus can’t work. 31 | 2. If the linux system can’t support yum command to install software, the [GDB], and [expect] software should be manual installed, before use Chaosblade-exec-cplus. 32 | 33 | 34 | ## Contributing 35 | We welcome every contribution, even if it is just a punctuation. See details of [CONTRIBUTING](CONTRIBUTING.md) 36 | 37 | 38 | ## Bugs and Feedback 39 | For bug report, questions and discussions please submit [GitHub Issues](https://github.com/chaosblade-io/chaosblade-exec-cplus/issues). 40 | 41 | Contact us: chaosblade.io.01@gmail.com 42 | 43 | Gitter room: [chaosblade community](https://gitter.im/chaosblade-io/community) 44 | 45 | 46 | ## License 47 | Chaosblade-exec-cplus is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text. 48 | -------------------------------------------------------------------------------- /build/image/musl/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.20.13 2 | LABEL maintainer="Changjun Xiao" 3 | 4 | # # The image is used to build chaosblade for musl 5 | RUN wget http://www.musl-libc.org/releases/musl-1.1.21.tar.gz \ 6 | && tar -zxvf musl-1.1.21.tar.gz \ 7 | && rm musl-1.1.21.tar.gz \ 8 | && cd musl* \ 9 | && ./configure \ 10 | && make \ 11 | && make install \ 12 | && rm -rf musl* 13 | 14 | RUN apt-get update \ 15 | && apt-get install unzip 16 | 17 | ENV CC /usr/local/musl/bin/musl-gcc 18 | ENV GOOS linux 19 | 20 | ENTRYPOINT [ "make" ] 21 | -------------------------------------------------------------------------------- /build/spec.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "log" 21 | "os" 22 | 23 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 24 | "github.com/chaosblade-io/chaosblade-spec-go/util" 25 | 26 | "github.com/chaosblade-io/chaosblade-exec-cplus/module" 27 | ) 28 | 29 | func main() { 30 | if len(os.Args) != 2 { 31 | log.Panicln("less yaml file path") 32 | } 33 | err := util.CreateYamlFile(getModels(), os.Args[1]) 34 | if err != nil { 35 | log.Panicf("create yaml file error, %v", err) 36 | } 37 | } 38 | 39 | // getModels returns experiment models in the project 40 | func getModels() *spec.Models { 41 | modelCommandSpecs := []spec.ExpModelCommandSpec{ 42 | module.NewCPlusCommandModelSpec(), 43 | } 44 | prepareModel := spec.ExpPrepareModel{ 45 | PrepareType: "cplus", 46 | PrepareFlags: []spec.ExpFlag{ 47 | { 48 | Name: "port", 49 | Desc: "server port to be listening", 50 | }, 51 | { 52 | Name: "ip", 53 | Desc: "The ip address bound to the service", 54 | }, 55 | }, 56 | PrepareRequired: true, 57 | } 58 | specModels := make([]*spec.Models, 0) 59 | for _, modeSpec := range modelCommandSpecs { 60 | specModel := util.ConvertSpecToModels(modeSpec, prepareModel, "host") 61 | specModels = append(specModels, specModel) 62 | } 63 | return util.MergeModels(specModels...) 64 | } 65 | -------------------------------------------------------------------------------- /common/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | const ( 20 | TargetName = "cplus" 21 | DelayActionName = "delay" 22 | ReturnErrorDataActionName = "return" 23 | VariableModifyActionName = "modify" 24 | FileKeyword = "file " 25 | SetEnvLdLibraryPath = "set env LD_LIBRARY_PATH " 26 | SleepMilliseconds = 1000 27 | CorePoolSize = 1 28 | MaximumPoolSize = 1 29 | KeepAliveTime = 0 30 | BinName = "chaosblade-exec-cplus" 31 | ) 32 | 33 | const ( 34 | InitializationScript = "shell_initialization.sh" 35 | RemoveProcessScript = "shell_remove_process.sh" 36 | ResponseDelayScript = "shell_response_delay.sh" 37 | ResponseDelayAttachScript = "shell_response_delay_attach.sh" 38 | ResponseDelayAttachParentScript = "shell_response_delay_attach_parent.sh" 39 | BreakAndReturnScript = "shell_break_and_return.sh" 40 | BreakAndReturnAttachScript = "shell_break_and_return_attach.sh" 41 | BreakAndReturnAttachParentScript = "shell_break_and_return_attach_parent.sh" 42 | ModifyVariableScript = "shell_modify_variable.sh" 43 | ModifyVariableAttachScript = "shell_modify_variable_attach.sh" 44 | ModifyVariableAttachParentScript = "shell_modify_variable_attach_parent.sh" 45 | CheckProcessIdScript = "shell_check_process_id.sh" 46 | CheckProcessDuplicateScript = "shell_check_process_duplicate.sh" 47 | ) 48 | -------------------------------------------------------------------------------- /common/signal.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "context" 21 | "os" 22 | "os/signal" 23 | "runtime" 24 | "syscall" 25 | 26 | "github.com/chaosblade-io/chaosblade-spec-go/log" 27 | ) 28 | 29 | type ShutdownHook interface { 30 | Shutdown() error 31 | } 32 | 33 | func Hold(hooks ...ShutdownHook) { 34 | sig := make(chan os.Signal, 1) 35 | signal.Notify(sig, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) 36 | buf := make([]byte, 1<<10) 37 | for { 38 | switch <-sig { 39 | case syscall.SIGINT, syscall.SIGTERM: 40 | log.Warnf(context.TODO(), "received SIGINT/SIGTERM, exit") 41 | for _, hook := range hooks { 42 | hook.Shutdown() 43 | } 44 | return 45 | case syscall.SIGQUIT: 46 | for _, hook := range hooks { 47 | hook.Shutdown() 48 | } 49 | len := runtime.Stack(buf, true) 50 | log.Warnf(context.TODO(), "received SIGQUIT\n%s\n", buf[:len]) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "log" 21 | "os" 22 | "os/exec" 23 | "path" 24 | "path/filepath" 25 | 26 | "github.com/chaosblade-io/chaosblade-spec-go/util" 27 | ) 28 | 29 | var proPath string 30 | 31 | // GetProgramPath 32 | func GetProgramPath() string { 33 | if proPath != "" { 34 | return proPath 35 | } 36 | dir, err := exec.LookPath(os.Args[0]) 37 | if err != nil { 38 | log.Fatalf("can not get the process path, %v", err) 39 | } 40 | if p, err := os.Readlink(dir); err == nil { 41 | dir = p 42 | } 43 | proPath, err = filepath.Abs(filepath.Dir(dir)) 44 | if err != nil { 45 | log.Fatalf("can not get the full process path, %v", err) 46 | } 47 | return proPath 48 | } 49 | 50 | var scriptPath string 51 | 52 | func GetScriptPath() string { 53 | if scriptPath != "" { 54 | return scriptPath 55 | } 56 | scriptPath = path.Join(GetProgramPath(), "script") 57 | return scriptPath 58 | } 59 | 60 | var chaosbladeLogPath string 61 | 62 | // chaosblade-VERSION/lib/cplus 63 | func GetChaosBladeLogPath() string { 64 | if chaosbladeLogPath != "" { 65 | return chaosbladeLogPath 66 | } 67 | chaosbladeLogPath = path.Join(path.Dir(path.Dir(GetProgramPath())), "logs", "chaosblade.log") 68 | 69 | if util.IsExist(chaosbladeLogPath) { 70 | return chaosbladeLogPath 71 | } 72 | err := os.MkdirAll(path.Dir(chaosbladeLogPath), os.ModePerm) 73 | if err != nil { 74 | chaosbladeLogPath = path.Join(GetProgramPath(), "chaosblade.log") 75 | } 76 | return chaosbladeLogPath 77 | } 78 | -------------------------------------------------------------------------------- /controller/controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import "net/http" 20 | 21 | type Controller interface { 22 | GetControllerName() string 23 | GetRequestHandler() func(writer http.ResponseWriter, request *http.Request) 24 | } 25 | 26 | var Controllers = []Controller{ 27 | &CreateController{}, 28 | &DestroyController{}, 29 | &RemoveController{}, 30 | &StatusController{}, 31 | } 32 | -------------------------------------------------------------------------------- /controller/create.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net/http" 23 | 24 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 25 | 26 | "github.com/chaosblade-io/chaosblade-exec-cplus/common" 27 | ) 28 | 29 | const CreateName = "create" 30 | 31 | type CreateController struct { 32 | } 33 | 34 | func (c *CreateController) GetControllerName() string { 35 | return CreateName 36 | } 37 | 38 | func (c *CreateController) GetRequestHandler() func(writer http.ResponseWriter, request *http.Request) { 39 | return func(writer http.ResponseWriter, request *http.Request) { 40 | expModel, suid, err := convertRequestToExpModel(request) 41 | if err != nil { 42 | fmt.Fprintf(writer, spec.ResponseFailWithFlags(spec.CommandIllegal, err).Print()) 43 | return 44 | } 45 | actionModel := Manager.Actions[expModel.ActionName] 46 | if actionModel == nil { 47 | fmt.Fprintf(writer, spec.ResponseFailWithFlags(spec.ActionNotSupport, expModel.ActionName).Print()) 48 | return 49 | } 50 | // record 51 | err = Manager.Record(suid, expModel) 52 | if err != nil { 53 | fmt.Fprintf(writer, spec.ResponseFailWithFlags(spec.DatabaseError, "record", err).Print()) 54 | return 55 | } 56 | response := actionModel.Executor().Exec(suid, context.Background(), expModel) 57 | if !response.Success { 58 | Manager.Remove(suid) 59 | } 60 | fmt.Fprintf(writer, response.Print()) 61 | } 62 | } 63 | 64 | func convertRequestToExpModel(request *http.Request) (*spec.ExpModel, string, error) { 65 | err := request.ParseForm() 66 | if err != nil { 67 | return nil, "", err 68 | } 69 | flags := make(map[string]string, 0) 70 | 71 | suid := request.Form.Get("suid") 72 | if suid == "" { 73 | return nil, "", fmt.Errorf("illegal suid parameter") 74 | } 75 | target := request.Form.Get("target") 76 | if target != common.TargetName { 77 | return nil, suid, fmt.Errorf("the target not support") 78 | } 79 | action := request.Form.Get("action") 80 | if action == "" { 81 | return nil, suid, fmt.Errorf("less action parameter") 82 | } 83 | breakLine := request.Form.Get("breakLine") 84 | if breakLine == "" { 85 | return nil, suid, fmt.Errorf("less breakLine parameter") 86 | } 87 | flags["breakLine"] = breakLine 88 | fileLocateAndName := request.Form.Get("fileLocateAndName") 89 | if fileLocateAndName == "" { 90 | return nil, suid, fmt.Errorf("less fileLocateAndName parameter") 91 | } 92 | flags["fileLocateAndName"] = fileLocateAndName 93 | forkMode := request.Form.Get("forkMode") 94 | if forkMode == "" { 95 | return nil, suid, fmt.Errorf("less forkMode parameter") 96 | } 97 | flags["forkMode"] = forkMode 98 | processName := request.Form.Get("processName") 99 | if processName == "" { 100 | return nil, suid, fmt.Errorf("less processName parameter") 101 | } 102 | flags["processName"] = processName 103 | libLoad := request.Form.Get("libLoad") 104 | if libLoad != "" { 105 | libLoad = common.SetEnvLdLibraryPath + libLoad 106 | } 107 | flags["libLoad"] = libLoad 108 | initParams := request.Form.Get("initParams") 109 | if initParams != "" { 110 | flags["initParams"] = initParams 111 | } 112 | 113 | // TODO delay 114 | delayDuration := request.Form.Get("delayDuration") 115 | if delayDuration != "" { 116 | flags["delayDuration"] = delayDuration 117 | } 118 | // return 119 | returnValue := request.Form.Get("returnValue") 120 | if returnValue != "" { 121 | flags["returnValue"] = returnValue 122 | } 123 | 124 | // modify 125 | variableValue := request.Form.Get("variableValue") 126 | if variableValue != "" { 127 | flags["variableValue"] = variableValue 128 | } 129 | variableName := request.Form.Get("variableName") 130 | if variableName != "" { 131 | flags["variableName"] = variableName 132 | } 133 | 134 | return &spec.ExpModel{ 135 | Target: common.TargetName, 136 | Scope: "", 137 | ActionName: action, 138 | ActionFlags: flags, 139 | }, suid, nil 140 | } 141 | -------------------------------------------------------------------------------- /controller/destroy.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net/http" 23 | "path" 24 | "strings" 25 | 26 | "github.com/chaosblade-io/chaosblade-exec-cplus/common" 27 | "github.com/chaosblade-io/chaosblade-spec-go/channel" 28 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 29 | ) 30 | 31 | const DestroyName = "destroy" 32 | 33 | type DestroyController struct { 34 | } 35 | 36 | func (d *DestroyController) GetControllerName() string { 37 | return DestroyName 38 | } 39 | 40 | func (d *DestroyController) GetRequestHandler() func(writer http.ResponseWriter, request *http.Request) { 41 | return func(writer http.ResponseWriter, request *http.Request) { 42 | err := request.ParseForm() 43 | if err != nil { 44 | fmt.Fprintf(writer, spec.ResponseFailWithFlags(spec.CommandIllegal, err).Print()) 45 | return 46 | } 47 | suid := request.Form.Get("suid") 48 | if suid == "" { 49 | fmt.Fprintf(writer, spec.ResponseFailWithFlags(spec.ParameterLess, "suid").Print()) 50 | return 51 | } 52 | expModel := Manager.Experiments[suid] 53 | if expModel == nil { 54 | fmt.Fprintf(writer, spec.ReturnSuccess("the experiment not found").Print()) 55 | return 56 | } 57 | processName := expModel.ActionFlags["processName"] 58 | if processName == "" { 59 | fmt.Fprintf(writer, spec.ReturnSuccess("success").Print()) 60 | return 61 | } 62 | localChannel := channel.NewLocalChannel() 63 | pids, err := localChannel.GetPidsByProcessName(processName, context.Background()) 64 | if err == nil && len(pids) == 0 { 65 | fmt.Fprintf(writer, spec.ReturnSuccess("success").Print()) 66 | return 67 | } 68 | var pid string 69 | if len(pids) > 0 { 70 | pid = strings.Join(pids, ",") 71 | } 72 | 73 | response := localChannel.Run(context.Background(), 74 | path.Join(common.GetScriptPath(), common.RemoveProcessScript), pid) 75 | fmt.Fprintf(writer, response.Print()) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /controller/manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "sync" 21 | 22 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 23 | 24 | "github.com/chaosblade-io/chaosblade-exec-cplus/module" 25 | ) 26 | 27 | type ExpManager struct { 28 | // 29 | Experiments map[string]*spec.ExpModel 30 | // 31 | Actions map[string]*spec.ActionModel 32 | } 33 | 34 | var Manager *ExpManager 35 | var once sync.Once 36 | 37 | func init() { 38 | once.Do(func() { 39 | Manager = &ExpManager{ 40 | Experiments: make(map[string]*spec.ExpModel, 0), 41 | Actions: make(map[string]*spec.ActionModel, 0), 42 | } 43 | 44 | modelSpec := module.NewCPlusCommandModelSpec() 45 | actions := modelSpec.Actions() 46 | for _, action := range actions { 47 | actionModel := &spec.ActionModel{ 48 | ActionName: action.Name(), 49 | ActionAliases: action.Aliases(), 50 | ActionShortDesc: action.ShortDesc(), 51 | ActionLongDesc: action.LongDesc(), 52 | ActionMatchers: func() []spec.ExpFlag { 53 | matchers := make([]spec.ExpFlag, 0) 54 | for _, m := range action.Matchers() { 55 | matchers = append(matchers, spec.ExpFlag{ 56 | Name: m.FlagName(), 57 | Desc: m.FlagDesc(), 58 | NoArgs: m.FlagNoArgs(), 59 | Required: m.FlagRequired(), 60 | }) 61 | } 62 | return matchers 63 | }(), 64 | ActionFlags: func() []spec.ExpFlag { 65 | flags := make([]spec.ExpFlag, 0) 66 | for _, m := range action.Flags() { 67 | flags = append(flags, spec.ExpFlag{ 68 | Name: m.FlagName(), 69 | Desc: m.FlagDesc(), 70 | NoArgs: m.FlagNoArgs(), 71 | Required: m.FlagRequired(), 72 | }) 73 | } 74 | for _, m := range modelSpec.Flags() { 75 | flags = append(flags, spec.ExpFlag{ 76 | Name: m.FlagName(), 77 | Desc: m.FlagDesc(), 78 | NoArgs: m.FlagNoArgs(), 79 | Required: m.FlagRequired(), 80 | }) 81 | } 82 | return flags 83 | }(), 84 | } 85 | actionModel.SetExecutor(action.Executor()) 86 | Manager.Actions[action.Name()] = actionModel 87 | } 88 | }) 89 | } 90 | 91 | func (e *ExpManager) Record(suid string, expModel *spec.ExpModel) error { 92 | // TODO 93 | e.Experiments[suid] = expModel 94 | return nil 95 | } 96 | 97 | func (e *ExpManager) Remove(suid string) error { 98 | // TODO 99 | delete(e.Experiments, suid) 100 | return nil 101 | } 102 | -------------------------------------------------------------------------------- /controller/remove.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net/http" 23 | 24 | "github.com/chaosblade-io/chaosblade-spec-go/channel" 25 | ) 26 | 27 | const RemoveName = "remove" 28 | 29 | type RemoveController struct { 30 | } 31 | 32 | func (r *RemoveController) GetControllerName() string { 33 | return RemoveName 34 | } 35 | 36 | func (r *RemoveController) GetRequestHandler() func(writer http.ResponseWriter, request *http.Request) { 37 | return func(writer http.ResponseWriter, request *http.Request) { 38 | // TODO 暂时全部杀掉 gdb 39 | response := channel.NewLocalChannel().Run(context.Background(), "pkill", "-f gdb") 40 | fmt.Fprintf(writer, response.Print()) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /controller/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "fmt" 21 | "net/http" 22 | ) 23 | 24 | const StatusName = "status" 25 | 26 | type StatusController struct { 27 | } 28 | 29 | func (r *StatusController) GetControllerName() string { 30 | return StatusName 31 | } 32 | 33 | func (r *StatusController) GetRequestHandler() func(writer http.ResponseWriter, request *http.Request) { 34 | return func(writer http.ResponseWriter, request *http.Request) { 35 | fmt.Fprintf(writer, "success") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/chaosblade-io/chaosblade-exec-cplus 2 | 3 | go 1.20 4 | 5 | require github.com/chaosblade-io/chaosblade-spec-go v1.7.3 6 | 7 | require ( 8 | github.com/go-ole/go-ole v1.2.6 // indirect 9 | github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect 10 | github.com/shirou/gopsutil v3.21.11+incompatible // indirect 11 | github.com/sirupsen/logrus v1.4.2 // indirect 12 | github.com/tklauser/go-sysconf v0.3.9 // indirect 13 | github.com/tklauser/numcpus v0.3.0 // indirect 14 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 15 | golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 // indirect 16 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect 17 | gopkg.in/yaml.v2 v2.2.8 // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 2 | github.com/chaosblade-io/chaosblade-spec-go v1.7.3 h1:OhFFBCV4iNwOdKA7BPjtdSM5cJZrtZry7JBUyWEc83g= 3 | github.com/chaosblade-io/chaosblade-spec-go v1.7.3/go.mod h1:khF37h4B8tKfBlgqKGE/+2sWimvm+Mc1l3V8rY5rbOQ= 4 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= 7 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 8 | github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 9 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 10 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 11 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 12 | github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= 13 | github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 14 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 15 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 16 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 17 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 18 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 19 | github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= 20 | github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= 21 | github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= 22 | github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= 23 | github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= 24 | github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 25 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 26 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 27 | golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71 h1:ikCpsnYR+Ew0vu99XlDp55lGgDJdIMx3f4a18jfse/s= 28 | golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 29 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 30 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 31 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= 32 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 33 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 34 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 35 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "flag" 22 | "fmt" 23 | "log" 24 | "net/http" 25 | "os" 26 | "path" 27 | "time" 28 | 29 | "github.com/chaosblade-io/chaosblade-spec-go/channel" 30 | "github.com/chaosblade-io/chaosblade-spec-go/util" 31 | 32 | "github.com/chaosblade-io/chaosblade-exec-cplus/common" 33 | "github.com/chaosblade-io/chaosblade-exec-cplus/controller" 34 | ) 35 | 36 | type Config struct { 37 | Port int 38 | IP string 39 | nohup bool 40 | } 41 | 42 | func main() { 43 | config := &Config{} 44 | flag.StringVar(&config.IP, "ip", "", "The ip bounds on the service") 45 | flag.IntVar(&config.Port, "port", 9525, "The port bounds one the service") 46 | flag.BoolVar(&config.nohup, "nohup", false, "used by internal") 47 | 48 | flag.Parse() 49 | util.InitLog(util.Custom) 50 | ctx := context.WithValue(context.Background(), channel.ProcessKey, "nohup") 51 | pids, err := channel.NewLocalChannel().GetPidsByProcessName(common.BinName, ctx) 52 | if err != nil { 53 | log.Fatalf("query process failed, %v", err) 54 | } 55 | if len(pids) > 0 { 56 | log.Fatalf("process has been started, %+v", pids) 57 | } 58 | if config.nohup { 59 | start0(config) 60 | os.Exit(0) 61 | } 62 | err = start(config) 63 | if err != nil { 64 | log.Fatalf("start failed, %v", err) 65 | } 66 | log.Printf("success") 67 | os.Exit(0) 68 | } 69 | 70 | func start(config *Config) error { 71 | args := fmt.Sprintf("%s --nohup --port %d", path.Join(common.GetProgramPath(), common.BinName), config.Port) 72 | if config.IP != "" { 73 | args = fmt.Sprintf("%s --ip %s", args, config.IP) 74 | } 75 | cl := channel.NewLocalChannel() 76 | 77 | response := cl.Run(context.TODO(), "nohup", fmt.Sprintf("%s > %s 2>&1 &", args, common.GetChaosBladeLogPath())) 78 | if !response.Success { 79 | return fmt.Errorf(response.Err) 80 | } 81 | time.Sleep(time.Second) 82 | ctx := context.WithValue(context.Background(), channel.ProcessKey, "nohup") 83 | pids, err := cl.GetPidsByProcessName(common.BinName, ctx) 84 | if err != nil { 85 | return err 86 | } 87 | if len(pids) == 0 { 88 | return fmt.Errorf("process not found") 89 | } 90 | return nil 91 | } 92 | 93 | func start0(config *Config) { 94 | go func() { 95 | err := http.ListenAndServe(fmt.Sprintf("%s:%d", config.IP, config.Port), nil) 96 | if err != nil { 97 | log.Fatalf("start chaosblade-exec-cplus failed, %v", err) 98 | } 99 | }() 100 | 101 | for _, c := range controller.Controllers { 102 | http.HandleFunc("/"+c.GetControllerName(), c.GetRequestHandler()) 103 | } 104 | common.Hold() 105 | } 106 | -------------------------------------------------------------------------------- /module/common.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package module 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | ) 23 | 24 | func buildArgs(flags []string) string { 25 | args := "" 26 | for _, flag := range flags { 27 | if flag != "" { 28 | args = fmt.Sprintf(`%s %s`, args, flag) 29 | } else { 30 | args = fmt.Sprintf(`%s ''`, args) 31 | } 32 | } 33 | return strings.TrimSpace(args) 34 | } 35 | -------------------------------------------------------------------------------- /module/errorreturned.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package module 18 | 19 | import ( 20 | "context" 21 | "path" 22 | 23 | "github.com/chaosblade-io/chaosblade-exec-cplus/common" 24 | "github.com/chaosblade-io/chaosblade-spec-go/channel" 25 | "github.com/chaosblade-io/chaosblade-spec-go/log" 26 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 27 | ) 28 | 29 | type ErrorReturnedActionSpec struct { 30 | spec.BaseExpActionCommandSpec 31 | } 32 | 33 | func NewErrorReturnedActionSpec() spec.ExpActionCommandSpec { 34 | return &ErrorReturnedActionSpec{ 35 | spec.BaseExpActionCommandSpec{ 36 | ActionMatchers: []spec.ExpFlagSpec{}, 37 | ActionFlags: []spec.ExpFlagSpec{ 38 | &spec.ExpFlag{ 39 | Name: "returnValue", 40 | Desc: "Value returned. If you want return null, set --returnValue null", 41 | Required: true, 42 | }, 43 | }, 44 | ActionExecutor: &ErrorReturnedExecutor{}, 45 | }, 46 | } 47 | } 48 | 49 | func (e ErrorReturnedActionSpec) Name() string { 50 | return "return" 51 | } 52 | 53 | func (e ErrorReturnedActionSpec) Aliases() []string { 54 | return []string{} 55 | } 56 | 57 | func (e ErrorReturnedActionSpec) ShortDesc() string { 58 | return "error returned" 59 | } 60 | 61 | func (e ErrorReturnedActionSpec) LongDesc() string { 62 | return "error returned" 63 | } 64 | 65 | type ErrorReturnedExecutor struct { 66 | channel spec.Channel 67 | } 68 | 69 | func (e *ErrorReturnedExecutor) Name() string { 70 | return "return" 71 | } 72 | 73 | func (e *ErrorReturnedExecutor) Exec(uid string, ctx context.Context, model *spec.ExpModel) *spec.Response { 74 | if _, ok := spec.IsDestroy(ctx); ok { 75 | return spec.ResponseFailWithFlags(spec.CommandIllegal, "destroy") 76 | } 77 | returnValue := model.ActionFlags["returnValue"] 78 | if returnValue == "" { 79 | return spec.ResponseFailWithFlags(spec.ParameterLess, "returnValue") 80 | } 81 | // search pid by process name 82 | processName := model.ActionFlags["processName"] 83 | if processName == "" { 84 | return spec.ResponseFailWithFlags(spec.ParameterLess, "processName") 85 | } 86 | processCtx := context.WithValue(context.Background(), channel.ExcludeProcessKey, "blade") 87 | pids, err := channel.NewLocalChannel().GetPidsByProcessName(processName, processCtx) 88 | if err != nil { 89 | log.Warnf(ctx, "get pids by %s process name err, %v", processName, err) 90 | } 91 | localChannel := channel.NewLocalChannel() 92 | if pids == nil || len(pids) == 0 { 93 | args := buildArgs([]string{ 94 | model.ActionFlags["fileLocateAndName"], 95 | model.ActionFlags["forkMode"], 96 | model.ActionFlags["libLoad"], 97 | model.ActionFlags["breakLine"], 98 | returnValue, 99 | model.ActionFlags["initParams"], 100 | }) 101 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.BreakAndReturnScript), args) 102 | } else { 103 | args := buildArgs([]string{ 104 | pids[0], 105 | model.ActionFlags["forkMode"], 106 | "", 107 | "", 108 | model.ActionFlags["breakLine"], 109 | returnValue, 110 | model.ActionFlags["initParams"], 111 | }) 112 | if "child" == model.ActionFlags["forkMode"] { 113 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.BreakAndReturnAttachScript), args) 114 | } 115 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.BreakAndReturnAttachParentScript), args) 116 | } 117 | } 118 | 119 | func (e *ErrorReturnedExecutor) SetChannel(channel spec.Channel) { 120 | e.channel = channel 121 | } 122 | -------------------------------------------------------------------------------- /module/linedelayed.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package module 18 | 19 | import ( 20 | "context" 21 | "path" 22 | 23 | "github.com/chaosblade-io/chaosblade-exec-cplus/common" 24 | "github.com/chaosblade-io/chaosblade-spec-go/channel" 25 | "github.com/chaosblade-io/chaosblade-spec-go/log" 26 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 27 | ) 28 | 29 | type LineDelayedActionSpec struct { 30 | spec.BaseExpActionCommandSpec 31 | } 32 | 33 | func NewLineDelayedActionSpec() spec.ExpActionCommandSpec { 34 | return &LineDelayedActionSpec{ 35 | spec.BaseExpActionCommandSpec{ 36 | ActionMatchers: []spec.ExpFlagSpec{}, 37 | ActionFlags: []spec.ExpFlagSpec{ 38 | &spec.ExpFlag{ 39 | Name: "delayDuration", 40 | Desc: "delay time, unit is second", 41 | Required: true, 42 | }, 43 | }, 44 | ActionExecutor: &LineDelayedExecutor{}, 45 | }, 46 | } 47 | } 48 | 49 | func (l LineDelayedActionSpec) Name() string { 50 | return "delay" 51 | } 52 | 53 | func (l LineDelayedActionSpec) Aliases() []string { 54 | return []string{} 55 | } 56 | 57 | func (l LineDelayedActionSpec) ShortDesc() string { 58 | return "Code line delayed" 59 | } 60 | 61 | func (l LineDelayedActionSpec) LongDesc() string { 62 | return "Code line delayed" 63 | } 64 | 65 | type LineDelayedExecutor struct { 66 | channel spec.Channel 67 | } 68 | 69 | func (l *LineDelayedExecutor) Name() string { 70 | return "delay" 71 | } 72 | 73 | func (l *LineDelayedExecutor) Exec(uid string, ctx context.Context, model *spec.ExpModel) *spec.Response { 74 | delayDuration := model.ActionFlags["delayDuration"] 75 | if delayDuration == "" { 76 | return spec.ResponseFailWithFlags(spec.ParameterLess, "delayDuration") 77 | } 78 | // search pid by process name 79 | processName := model.ActionFlags["processName"] 80 | if processName == "" { 81 | return spec.ResponseFailWithFlags(spec.ParameterLess, "processName") 82 | } 83 | processCtx := context.WithValue(context.Background(), channel.ExcludeProcessKey, "blade") 84 | pids, err := channel.NewLocalChannel().GetPidsByProcessName(processName, processCtx) 85 | if err != nil { 86 | log.Warnf(ctx, "get pids by %s process name err, %v", processName, err) 87 | } 88 | localChannel := channel.NewLocalChannel() 89 | if pids == nil || len(pids) == 0 { 90 | args := buildArgs([]string{ 91 | model.ActionFlags["fileLocateAndName"], 92 | model.ActionFlags["forkMode"], 93 | model.ActionFlags["libLoad"], 94 | model.ActionFlags["breakLine"], 95 | delayDuration, 96 | model.ActionFlags["initParams"], 97 | }) 98 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.ResponseDelayScript), args) 99 | } else { 100 | args := buildArgs([]string{ 101 | pids[0], 102 | model.ActionFlags["forkMode"], 103 | "", 104 | "", 105 | model.ActionFlags["breakLine"], 106 | delayDuration, 107 | model.ActionFlags["initParams"], 108 | }) 109 | if "child" == model.ActionFlags["forkMode"] { 110 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.ResponseDelayAttachScript), args) 111 | } 112 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.ResponseDelayAttachParentScript), args) 113 | } 114 | } 115 | 116 | func (l *LineDelayedExecutor) SetChannel(channel spec.Channel) { 117 | l.channel = channel 118 | } 119 | -------------------------------------------------------------------------------- /module/module.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package module 18 | 19 | import ( 20 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 21 | ) 22 | 23 | type CPlusExpModuleSpec struct { 24 | spec.BaseExpModelCommandSpec 25 | } 26 | 27 | func NewCPlusCommandModelSpec() spec.ExpModelCommandSpec { 28 | return &CPlusExpModuleSpec{ 29 | spec.BaseExpModelCommandSpec{ 30 | ExpScope: "host", 31 | ExpActions: []spec.ExpActionCommandSpec{ 32 | NewErrorReturnedActionSpec(), 33 | NewLineDelayedActionSpec(), 34 | NewVariableModifiedActionSpec(), 35 | }, 36 | ExpFlags: []spec.ExpFlagSpec{ 37 | &spec.ExpFlag{ 38 | Name: "breakLine", 39 | Desc: "Injection line in source code", 40 | Required: true, 41 | }, 42 | &spec.ExpFlag{ 43 | Name: "fileLocateAndName", 44 | Desc: "Startup file location and name", 45 | Required: true, 46 | }, 47 | &spec.ExpFlag{ 48 | Name: "initParams", 49 | Desc: "Initialization parameters for program startup (such as port number)", 50 | Required: false, 51 | }, 52 | &spec.ExpFlag{ 53 | Name: "forkMode", 54 | Desc: "Fault injection into child or parent processes (sub process:child ; main process:parent)", 55 | Required: true, 56 | }, 57 | &spec.ExpFlag{ 58 | Name: "processName", 59 | Desc: "Application process name", 60 | Required: true, 61 | }, 62 | &spec.ExpFlag{ 63 | Name: "libLoad", 64 | Desc: "If the class library needs to be loaded when the program starts, input the class library address", 65 | Required: false, 66 | }, 67 | }, 68 | }, 69 | } 70 | } 71 | 72 | func (c *CPlusExpModuleSpec) Name() string { 73 | return "cplus" 74 | } 75 | 76 | func (c *CPlusExpModuleSpec) ShortDesc() string { 77 | return "C++ chaos experiments" 78 | } 79 | 80 | func (c *CPlusExpModuleSpec) LongDesc() string { 81 | return "C++ chaos experiments contain code line delayed, variable modified and err returned" 82 | } 83 | 84 | func (c *CPlusExpModuleSpec) Example() string { 85 | // TODO 86 | return "" 87 | } 88 | -------------------------------------------------------------------------------- /module/variablemodified.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2020 Alibaba Group Holding Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package module 18 | 19 | import ( 20 | "context" 21 | "path" 22 | 23 | "github.com/chaosblade-io/chaosblade-exec-cplus/common" 24 | "github.com/chaosblade-io/chaosblade-spec-go/channel" 25 | "github.com/chaosblade-io/chaosblade-spec-go/log" 26 | "github.com/chaosblade-io/chaosblade-spec-go/spec" 27 | ) 28 | 29 | type VariableModifiedActionSpec struct { 30 | spec.BaseExpActionCommandSpec 31 | } 32 | 33 | func NewVariableModifiedActionSpec() spec.ExpActionCommandSpec { 34 | return &VariableModifiedActionSpec{ 35 | spec.BaseExpActionCommandSpec{ 36 | ActionMatchers: []spec.ExpFlagSpec{}, 37 | ActionFlags: []spec.ExpFlagSpec{ 38 | &spec.ExpFlag{ 39 | Name: "variableName", 40 | Desc: "The name of the modified variable", 41 | Required: true, 42 | }, 43 | &spec.ExpFlag{ 44 | Name: "variableValue", 45 | Desc: "The value of the modified variable", 46 | Required: true, 47 | }, 48 | }, 49 | ActionExecutor: &VariableModifiedExecutor{}, 50 | }, 51 | } 52 | } 53 | 54 | func (v *VariableModifiedActionSpec) Name() string { 55 | return "modify" 56 | } 57 | 58 | func (v *VariableModifiedActionSpec) Aliases() []string { 59 | return []string{} 60 | } 61 | 62 | func (v *VariableModifiedActionSpec) ShortDesc() string { 63 | return "Modify value of the variable in source code when program running" 64 | } 65 | 66 | func (v *VariableModifiedActionSpec) LongDesc() string { 67 | return "Modify value of the variable in source code when program running" 68 | } 69 | 70 | type VariableModifiedExecutor struct { 71 | channel spec.Channel 72 | } 73 | 74 | func (v *VariableModifiedExecutor) Name() string { 75 | return "modify" 76 | } 77 | 78 | func (v *VariableModifiedExecutor) Exec(uid string, ctx context.Context, model *spec.ExpModel) *spec.Response { 79 | variableName := model.ActionFlags["variableName"] 80 | if variableName == "" { 81 | return spec.ResponseFailWithFlags(spec.ParameterLess, "variableName") 82 | } 83 | variableValue := model.ActionFlags["variableValue"] 84 | if variableValue == "" { 85 | return spec.ResponseFailWithFlags(spec.ParameterLess, "variableValue") 86 | } 87 | // search pid by process name 88 | processName := model.ActionFlags["processName"] 89 | if processName == "" { 90 | return spec.ResponseFailWithFlags(spec.ParameterLess, "processName") 91 | } 92 | processCtx := context.WithValue(context.Background(), channel.ExcludeProcessKey, "blade") 93 | pids, err := channel.NewLocalChannel().GetPidsByProcessName(processName, processCtx) 94 | if err != nil { 95 | log.Warnf(ctx, "get pids by %s process name err, %v", processName, err) 96 | } 97 | localChannel := channel.NewLocalChannel() 98 | if pids == nil || len(pids) == 0 { 99 | args := buildArgs([]string{ 100 | model.ActionFlags["fileLocateAndName"], 101 | model.ActionFlags["forkMode"], 102 | model.ActionFlags["libLoad"], 103 | model.ActionFlags["breakLine"], 104 | variableName, 105 | variableValue, 106 | model.ActionFlags["initParams"], 107 | }) 108 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.ModifyVariableScript), args) 109 | } else { 110 | args := buildArgs([]string{ 111 | pids[0], 112 | model.ActionFlags["forkMode"], 113 | "", 114 | "", 115 | model.ActionFlags["breakLine"], 116 | variableName, 117 | variableValue, 118 | model.ActionFlags["initParams"], 119 | }) 120 | if "child" == model.ActionFlags["forkMode"] { 121 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.ModifyVariableAttachScript), args) 122 | } 123 | return localChannel.Run(context.Background(), path.Join(common.GetScriptPath(), common.ModifyVariableAttachParentScript), args) 124 | } 125 | } 126 | 127 | func (v *VariableModifiedExecutor) SetChannel(channel spec.Channel) { 128 | v.channel = channel 129 | } 130 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 4.0.0 22 | 23 | com.alibaba.chaosblade 24 | chaosblade-exec-cplus 25 | 1.1-SNAPSHOT 26 | 27 | 28 | UTF-8 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-parent 34 | 1.3.1.RELEASE 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-web 41 | 42 | 43 | 44 | 45 | org.apache.commons 46 | commons-lang3 47 | 3.8.1 48 | 49 | 50 | 51 | 52 | chaosblade-exec-cplus 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /script/shell_break_and_return.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb 5 | expect { 6 | \"gdb\" {send \"file $1\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"set pagination off\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $4\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"r $5\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"r $6\n\";} 37 | } 38 | 39 | interact 40 | " -------------------------------------------------------------------------------- /script/shell_break_and_return_attach.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb -q attach $1 5 | expect { 6 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set pagination off\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"$4\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $5\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"return $6\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"r $7\n\";} 37 | } 38 | expect { 39 | \"beginning\" {send \"y\n\";} 40 | } 41 | 42 | interact 43 | " -------------------------------------------------------------------------------- /script/shell_break_and_return_attach_parent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb -q attach $1 5 | expect { 6 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set pagination off\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"$4\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $5\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"return $6\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"c\n\";} 37 | } 38 | 39 | interact 40 | " -------------------------------------------------------------------------------- /script/shell_check_process_duplicate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ps -ef|grep $1|grep 'gdb' -------------------------------------------------------------------------------- /script/shell_check_process_id.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ps -ef|grep $1|grep -v 'grep'|grep -v 'initParams'|grep -v 'shell_check_process_id'| awk '{print $2}' -------------------------------------------------------------------------------- /script/shell_initialization.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install gdb 4 | if ! [ -x "$(command -v gdb)" ]; then 5 | yes | yum install gdb 6 | echo 'Pass: gdb has been installed.' 7 | else 8 | echo 'Pass: gdb has been installed.' 9 | fi 10 | 11 | # Install expect 12 | if ! [ -x "$(command -v expect)" ]; then 13 | yes | yum install expect 14 | echo 'Pass: expect has been installed.' 15 | exit 1 16 | else 17 | echo 'Pass: expect already has been installed.' 18 | exit 1 19 | fi -------------------------------------------------------------------------------- /script/shell_modify_variable.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb 5 | expect { 6 | \"gdb\" {send \"file $1\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"set pagination off\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $4\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"set $5=$6\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"r $7\n\";} 37 | } 38 | 39 | interact 40 | " -------------------------------------------------------------------------------- /script/shell_modify_variable_attach.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb -q attach $1 5 | expect { 6 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set pagination off\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"$4\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $5\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"set $6 = $7\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"r $8\n\";} 37 | } 38 | expect { 39 | \"beginning\" {send \"y\n\";} 40 | } 41 | 42 | interact 43 | " -------------------------------------------------------------------------------- /script/shell_modify_variable_attach_parent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb -q attach $1 5 | expect { 6 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set pagination off\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"$4\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $5\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"set $6 = $7\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"c\n\";} 37 | } 38 | 39 | interact 40 | " -------------------------------------------------------------------------------- /script/shell_remove_process.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pkill -f gdb 4 | 5 | if [[ -n "$1" ]]; then 6 | kill -9 "$1" 7 | fi -------------------------------------------------------------------------------- /script/shell_response_delay.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb 5 | expect { 6 | \"gdb\" {send \"file $1\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"set pagination off\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $4\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"shell sleep $5\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"r $6\n\";} 37 | } 38 | 39 | interact 40 | " -------------------------------------------------------------------------------- /script/shell_response_delay_attach.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb -q attach $1 5 | expect { 6 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set pagination off\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"$4\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $5\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"shell sleep $6\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"r $7\n\";} 37 | } 38 | expect { 39 | \"beginning\" {send \"y\n\";} 40 | } 41 | 42 | interact 43 | " -------------------------------------------------------------------------------- /script/shell_response_delay_attach_parent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | expect -c " 4 | spawn gdb -q attach $1 5 | expect { 6 | \"gdb\" {send \"set follow-fork-mode $2\n\";} 7 | } 8 | expect { 9 | \"gdb\" {send \"set pagination off\n\";} 10 | } 11 | expect { 12 | \"gdb\" {send \"$3\n\";} 13 | } 14 | expect { 15 | \"gdb\" {send \"$4\n\";} 16 | } 17 | expect { 18 | \"gdb\" {send \"b $5\n\";} 19 | } 20 | expect { 21 | \"gdb\" {send \"commands\n\";} 22 | } 23 | expect { 24 | \">\" {send \"silent\n\"} 25 | } 26 | expect { 27 | \">\" {send \"shell sleep $6\n\"} 28 | } 29 | expect { 30 | \">\" {send \"cont\n\"} 31 | } 32 | expect { 33 | \">\" {send \"end\n\"} 34 | } 35 | expect { 36 | \"gdb\" {send \"c\n\";} 37 | } 38 | 39 | interact 40 | " --------------------------------------------------------------------------------