如何通过Golang执行mysql_tzinfo_to_sql并避免密码在ps中暴露?
解决Golang执行MySQL时区导入脚本时密码泄露问题
当你通过exec.Command执行带密码的MySQL命令时,密码会出现在ps -aux的进程列表里,这是因为命令行参数是系统公开可见的。可以用以下几种方法解决:
方案1:使用临时配置文件
创建一个仅当前用户可读的临时MySQL客户端配置文件,写入用户名和密码,命令中引用该文件,执行完成后立即删除文件,避免泄露。
示例代码:
package main import ( "fmt" "os" "os/exec" "io/ioutil" ) func main() { username := "your_user" password := "your_pass" // 构造临时配置文件内容 cnfContent := fmt.Sprintf(`[client] user=%s password=%s `, username, password) // 创建临时文件,权限设为600(仅当前用户可读可写) tmpFile, err := ioutil.TempFile("", "mysql_tmp_*.cnf") if err != nil { panic(err) } defer os.Remove(tmpFile.Name()) // 执行完成后删除临时文件 if _, err := tmpFile.WriteString(cnfContent); err != nil { panic(err) } tmpFile.Close() // 构造脚本,通过--defaults-extra-file引用临时配置 script := fmt.Sprintf(`mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql --defaults-extra-file=%s mysql`, tmpFile.Name()) cmd := exec.Command("bash", "-c", script) // 执行命令并处理结果 output, err := cmd.CombinedOutput() if err != nil { fmt.Printf("执行失败: %s\n输出: %s\n", err, output) return } fmt.Println("时区导入成功") }
方案2:通过标准输入传递密码
利用MySQL的--password参数(不带值),让程序从标准输入读取密码,同时通过Golang的管道将密码传入进程,避免密码出现在命令行。
示例代码:
package main import ( "fmt" "os/exec" "io" ) func main() { username := "your_user" password := "your_pass" // 构造脚本,使用--password参数(不带值)触发从stdin读密码 script := fmt.Sprintf(`mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u %s --password mysql`, username) cmd := exec.Command("bash", "-c", script) // 获取命令的标准输入管道 stdin, err := cmd.StdinPipe() if err != nil { panic(err) } // 启动命令 if err := cmd.Start(); err != nil { panic(err) } // 向标准输入写入密码,注意结尾要加换行符 _, err = io.WriteString(stdin, password+"\n") if err != nil { panic(err) } stdin.Close() // 等待命令执行完成 if err := cmd.Wait(); err != nil { fmt.Printf("执行失败: %s\n", err) return } fmt.Println("时区导入成功") }
方案3:使用环境变量
MySQL支持通过MYSQL_PWD环境变量传递密码,Golang中可以为执行的命令单独设置环境变量,避免密码出现在命令行参数中。
示例代码:
package main import ( "fmt" "os" "os/exec" ) func main() { username := "your_user" password := "your_pass" // 构造脚本,不包含任何密码参数 script := fmt.Sprintf(`mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u %s mysql`, username) cmd := exec.Command("bash", "-c", script) // 复制当前环境变量,添加MYSQL_PWD变量 cmd.Env = append(os.Environ(), fmt.Sprintf("MYSQL_PWD=%s", password)) // 执行命令并处理结果 output, err := cmd.CombinedOutput() if err != nil { fmt.Printf("执行失败: %s\n输出: %s\n", err, output) return } fmt.Println("时区导入成功") }
注意:方案3中的
MYSQL_PWD环境变量在部分MySQL版本中被标记为废弃,推荐优先使用方案1或方案2。
内容的提问来源于stack exchange,提问作者hatemath
相关产品推荐
相关产品推荐

