You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:55:31