当前Go程序以root运行时 如何以普通用户权限执行shell命令
实现方案
直接通过设置exec.Cmd的SysProcAttr属性指定运行用户的UID/GID即可,该操作仅root用户有权限执行,符合你当前用root启动主程序的场景。
修改步骤
- 导入
syscall包,如果需要动态获取用户UID/GID可额外导入os/user包 - 为cmd对象设置
SysProcAttr属性,通过Credential字段指定运行命令的用户ID和组ID - 若要top正常输出,交互式场景无需额外参数,非交互式场景可给top加
-bn 1参数指定批量输出
完整修改后的代码示例
# main.go package main import ( "context" "fmt" "os" "os/exec" "syscall" // 如需动态查询用户uid/gid可取消下面注释 // "os/user" // "strconv" ) func run() error { // 方式1:硬编码指定普通用户的UID和GID,可提前通过`id -u 用户名`、`id -g 用户名`命令查询 uid := uint32(1000) // 替换为你的普通用户实际UID gid := uint32(1000) // 替换为你的普通用户实际GID // 方式2:动态根据用户名获取UID/GID,取消下面注释即可使用 // u, err := user.Lookup("你的普通用户名") // if err != nil { // return err // } // uid64, _ := strconv.ParseUint(u.Uid, 10, 32) // gid64, _ := strconv.ParseUint(u.Gid, 10, 32) // uid := uint32(uid64) // gid := uint32(gid64) cmd := exec.CommandContext(context.TODO(), "bash", "-c", "top") // 核心配置:指定子命令运行身份 cmd.SysProcAttr = &syscall.SysProcAttr{ Credential: &syscall.Credential{ Uid: uid, Gid: gid, }, } cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } func main() { err := run() if err != nil { fmt.Println(false) return } fmt.Println(true) }
注意事项
- 该实现仅适用于Linux、macOS等Unix类操作系统,Windows系统无对应syscall实现
- 只有root身份运行的主进程有权限指定其他用户身份运行子命令,非root运行主程序会报错权限不足
- 如果运行top时出现终端显示异常,可给top命令添加
-b参数开启批量模式,适配非交互式运行场景
内容的提问来源于stack exchange,提问作者Yan Tao
相关产品推荐
相关产品推荐

