背景
每次在一个新环境独立部署后,如果是为了开发调试,都需要手动修改如下配置:
- 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))
}