背景
每次在一个新环境独立部署后,如果是为了开发调试,都需要手动修改如下配置:
- java.json文件:开启swagger、开启api访问
- 开启不同服务的debug日志,开启远程端口调试
可以写一个脚本来修改这些配置,可用的语言有很多,比如shell、python、go等,这里使用go语言,也算是学习golang的一个小任务。
代码
修改配置源码
package main import ( "bufio" "fmt" "io/ioutil" "os" "strings" "github.com/spf13/viper" ) const CONF_LOG_DEBUG = " -Dlogging.level.debug=debug" const CONF_REMOTE_PORT = " -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" const LAST_CHAR = "\"" func main() { fmt.Println("start update conf ...") // 修改java.json文件 updateJavaJsonMap := map[string]interface{}{ "app.gateway.refer_check": false, "app.swagger.enable": true, "base.api_auth_white_path": "/**", }updateJavaJson("/data/app/titan-config", "java", "json", updateJavaJsonMap) // 修改不同服务的xxx.conf文件 serverConfMap := map[string]string{ "/data/app/titan-detect-srv/detect-srv.conf": "5012", "/data/app/titan-wisteria/wisteria.conf": "5006", } updateServerConf(serverConfMap) fmt.Println("finish update conf ...") } /** * 修改java.json文件 * * @param updateJavaJsonMap:需要更新的配置项。key=配置项的key,value=配置项的value */ func updateJavaJson(configPath string, configName string, configType string, updateJavaJsonMap map[string]interface{}) { viper.AddConfigPath(configPath) viper.SetConfigName(configName) viper.SetConfigType(configType) if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { fmt.Println("找不到配置文件..") } else { fmt.Println("配置文件出错..") } } // kafka的配置,key是以.分割的,重新写入时,容易被分割成多个key,所以这里特别处理 dealKafkaProperties() // 更新配置 for updateKey, updateValue := range updateJavaJsonMap { viper.Set(updateKey, updateValue) } // 写入当前文件 viper.WriteConfig() } /** * kafka的配置,key是以.分割的,重新写入时,容易被分割成多个key,所以这里特别处理 */ func dealKafkaProperties() { var kafkaPropertiesMap map[string]string = make(map[string]string) kafkaPropertiesMap["sasl.jaas.config"] = "org.apache.kafka.common.security.plain.PlainLoginModule required \n username=\"qingteng\" \n password=\"${kafka.password}\";" kafkaPropertiesMap["sasl.mechanism"] = "PLAIN" kafkaPropertiesMap["security.protocol"] = "SASL_PLAINTEXT" viper.Set("kafka.properties", kafkaPropertiesMap) } /** * 修改不同服务的xxx.conf文件。修改内容包括:1、开启debug日志 2、增加远程调试端口 * * @param serverConfMap:需要修改的服务配置。key=配置文件路径,value=远程调试端口号 */ func updateServerConf(serverConfMap map[string]string) { for configPath, remotePort := range serverConfMap { modifySingleConf(configPath, remotePort) } } /** * 修改单个服务的xxx.conf文件 * */ func modifySingleConf(configPath, remotePort string) { newContent := getConfContent(configPath, remotePort) // os.O_TRUNC清空文件重新写入 file, err := os.OpenFile(configPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { panic(err) } writer := bufio.NewWriter(file) writer.WriteString(newContent) writer.Flush() } /** * 读取.conf文件内容,并添加配置项 */ func getConfContent(configPath, remotePort string) string { content, err := ioutil.ReadFile(configPath) if err != nil { panic(err) } contentStr := string(content) var appendStr string = "" if !strings.Contains(contentStr, CONF_LOG_DEBUG) { appendStr += CONF_LOG_DEBUG } if !strings.Contains(contentStr, remotePort) { appendStr += CONF_REMOTE_PORT + remotePort } if len(appendStr) == 0 { return contentStr } // 计算最后一个引号的位置,用于后面去掉引号及引号之后的字符 lastIndex := strings.LastIndex(contentStr, LAST_CHAR) deleteStrLen := len(contentStr) - lastIndex // 去掉引号之后的字符 contentStr1 := contentStr[:len(contentStr)-deleteStrLen] // 追加字符串 newContent := contentStr1 + appendStr + LAST_CHAR return newContent }
- 示例中的java.json文件,配置项不是固定的,数据格式是随意变化的。
- 如果希望 更新/新增 更多的 java.json 文件中的配置,在 updateJavaJsonMap 中直接添加即可。
- 这里默认只会修改conf文件中,wisteria 和 detect-srv 两个服务的配置,如果需要修改其他服务的,需要在 serverConfMap 中加上对应配置即可。
本地调试:
- 如果想在本地修改调试,需要先配置好GOPATH,然后安装 viper 组件。安装命令:go get -u github.com/spf13/viper
- 创建一个go文件(比如:update_conf.go),拷贝上面的源码后,执行 go run update_conf.go 即可运行(注意修改为本地的配置文件路径)。
服务器上运行:
- 创建一个go文件(比如:update_conf.go),拷贝上面的源码后,执行 go build update_conf.go 命令,会在同级目录下生成一个二进制的可执行文件 update_conf,然后拷贝到对应的服务器上,执行 ./update_conf 即可。
- 修改配置文件后,需要自行重启对应的服务。
重启服务源码
package main import ( "fmt" "os/exec" ) const DEFAULT_OPT string = "Y" /** * linux命令 */ func main() { restart() } /** * 重启服务 */ func restart() { restartService("detect-srv", "/data/app/titan-detect-srv/init.d/detect-srv") restartService("wisteria", "/data/app/titan-wisteria/init.d/wisteria") restartService("gateway", "/data/app/titan-gateway/init.d/gateway") } /** * 重启服务 * * @serviceName 服务名称 * @restartPath 重启脚本路径 */ func restartService(serviceName, restartPath string) { var result string fmt.Printf("restart %s [Y/N]? default is Y\n", serviceName) fmt.Print("Enter [Y/N]: ") fmt.Scanln(&result) if len(result) == 0 { result = DEFAULT_OPT } if result == DEFAULT_OPT { fmt.Printf("start restart %s...\n", serviceName) doExecCmd(restartPath, "restart") } } /** * 执行操作 */ func doExecCmd(name string, operate string) { cmd := exec.Command(name, operate) var output []byte var err error if output, err = cmd.CombinedOutput(); err != nil { fmt.Println("error is :", err) return } // 打印输出结果 fmt.Println(string(output)) }