The Go Programming Language
› http://golang.org/
› Go Playground
Go Projects
› Revel Web Framework
eber

各位爹,请教一个 golang 的问题!

  •  
  •   eber · Mar 18, 2024 · 4370 views
    This topic created in 969 days ago, the information mentioned may be changed or developed.

    各位 golang 大佬(爹),上午好!我有个菜鸡问题:如何使用 golang 的 exec.Command()函数执行 sudo ?

    背景:小弟在使用 chromedp 做一个爬虫,目前一切正常,唯一的遗憾就是每次运行之前需要手动在 macOS 的终端执行 sudo /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=19222 必须加 sudo 才能打开 chrome 调试窗口。因为 golang 可以执行终端命令,所以我想使用代码去唤醒调试窗口,但是测试下来好像无法全自动调用 sudo 命令(不输入密码或密码怎么传进去)。

    29 replies  •  2024-03-20 10:08:13 +08:00
    NessajCN
    NessajCN
    Mar 18, 2024❤️2
    1
    你用 sudo 执行爬虫程序不就好了
    imPrk
    imPrk
    Mar 18, 2024
    2
    cmd := exec.Command("sudo", "ls", "/root")
    eber
    eber
    OP
    Mar 18, 2024
    3
    @imPrk 试过了,不行。。。会一直卡住,因为没输入密码。
    pkoukk
    pkoukk
    Mar 18, 2024
    4
    go build -o main .
    sudo ./main
    eber
    eber
    OP
    Mar 18, 2024
    5
    @NessajCN 刚试了一下,sudo 执行程序还是不会弹出 chrome 调试页。19222 也没有在监听。
    dummyx
    dummyx
    Mar 18, 2024
    6
    你把运行用户的 sudo 设置 NOPASSWD 不就行了嘛。。
    imPrk
    imPrk
    Mar 18, 2024
    7
    @eber 你确定你的 Go 程式有使用 root 身份运行吗
    JEME
    JEME
    Mar 18, 2024
    8
    使用 pty 相关的库,应该可以?
    aloxaf
    aloxaf
    Mar 18, 2024
    9
    用 sudo -S 可以从标准输入接收密码,然后你就可以正常把密码传进去了
    yanghanlin
    yanghanlin
    Mar 18, 2024 via Android
    10
    sudo -S 然后密码通过 stdin 传进去?
    eber
    eber
    OP
    Mar 18, 2024
    11
    @NessajCN 抱歉,抱歉。。。找到问题了,确实 sudo 运行程序可以唤醒调试页面。应该是 chrome 路径问题。。。/Applications/Google Chrome.app/Contents/MacOS/Google Chrome 空格不能加转译。。。
    Yangsh853
    Yangsh853
    Mar 18, 2024
    12
    在 sudoers 给用户加 NOPASSWD ,就不用输密码了
    eber
    eber
    OP
    Mar 18, 2024
    13
    是的,这样确实可以,但是需要提前修改用户属性不太好。
    @fengxsong
    @Yangsh853
    eber
    eber
    OP
    Mar 18, 2024
    14
    @JEME 我去试一下先,有结果了我来说一下。
    eber
    eber
    OP
    Mar 18, 2024
    15
    @yanghanlin
    @aloxaf 也是个不错方法。
    somebody1
    somebody1
    Mar 18, 2024❤️2
    16
    这是学到精髓了呀,上周的那个帖子上大分!
    wOuv7i4e7XxsSOR1
    wOuv7i4e7XxsSOR1
    Mar 18, 2024
    17
    sudo -A
    proxychains
    proxychains
    Mar 18, 2024 via Android
    18
    提问的艺术
    cat9life
    cat9life
    Mar 18, 2024
    19
    辈分有点乱啊,一会爹一会自称小弟。(开个玩笑..
    lele140
    lele140
    Mar 18, 2024
    20
    现在 问问题都这么卷了吗?
    deplives
    deplives
    Mar 18, 2024
    21
    sudo 可以使用 -S 从 stdin 传入密码
    eber
    eber
    OP
    Mar 18, 2024❤️1
    22
    @lele140 虚心学习嘛 不磕碜!!!
    Leeeeex
    Leeeeex
    Mar 18, 2024
    23
    提问的艺术得更新了
    2Nfree
    2Nfree
    Mar 18, 2024
    24
    golang.org/x/crypto/ssh 包可以创建标准管道输出
    用 session.StdinPipe()
    2Nfree
    2Nfree
    Mar 18, 2024
    25
    @2Nfree 用这个办法可以输入 sudo 的密码,之前写过一个模仿 ansiable 的程序是这么做的,里面部分代码:
    package utils

    import (
    "batch-execution-tool/core"
    "bytes"
    "fmt"
    "golang.org/x/crypto/ssh"
    "os"
    "sync"
    )

    func ExecuteScripts() {
    var wg sync.WaitGroup
    defer wg.Wait()
    for _, ip := range core.Config.ServersIP {
    wg.Add(1)
    go func(ip string) {
    defer wg.Done()
    SSHClient, errSSH := createSSHConnect(ip)
    if errSSH != nil {
    core.Logger.Sugar().Errorf("创建 SSH 链接失败:\n%v", errSSH)
    return
    }
    for _, script := range core.Config.Scripts {
    for name := range script {
    err := exec(SSHClient, ip, name)
    if err != nil {
    core.Logger.Sugar().Errorf("在 IP 地址为:%v 的服务器,出现错误:\n%v", ip, err)
    } else {
    core.Logger.Sugar().Debugf("在 IP 地址为:%v 的服务器,执行脚本 %v 成功", ip, name)
    }
    }
    }
    }(ip)
    }
    }

    func exec(client *ssh.Client, ip, script string) error {
    core.Logger.Sugar().Debugf("正在 IP 地址为:%v 的服务器中执行脚本:%s", ip, script)
    session, err := client.NewSession()
    if err != nil {
    return err
    }
    var output bytes.Buffer
    session.Stderr = &output
    remoteDir := "scripts"
    if core.Config.Auth.Username == "root" {
    if err := session.Start("bash " + remoteDir + "/" + script + " > " + remoteDir + "/" + script + ".log"); err != nil {
    return fmt.Errorf("执行脚本 %s 失败: \n%s:%s", script, err, output.String())
    }
    if err := session.Wait(); err != nil {
    return fmt.Errorf("执行脚本 %s 失败: \n%s:%s", script, err, output.String())
    }
    } else {
    if err := session.RequestPty("xterm", 80, 40, ssh.TerminalModes{}); err != nil {
    return fmt.Errorf("请求 TTY 出错:%v ,\nos.Stderr:%v", err, os.Stderr)
    }
    stdin, err := session.StdinPipe()
    defer stdin.Close()
    if err != nil {
    return fmt.Errorf("创建标准管道输出错误: \n%v", err)
    }
    if err := session.Start("sudo bash " + remoteDir + "/" + script + " > " + remoteDir + "/" + script + ".log"); err != nil {
    return fmt.Errorf("执行脚本 %s 失败: \n%s:%s", script, err, output.String())
    }
    _, err = fmt.Fprintln(stdin, core.Config.Auth.Password)
    if err != nil {
    return fmt.Errorf("使用标准管道输如密码错误: \n%v", err)
    }
    if err := session.Wait(); err != nil {
    return fmt.Errorf("执行脚本 %s 失败: \n%s:%s", script, err, output.String())
    }
    }
    session.Close()
    return nil
    }
    eber
    eber
    OP
    Mar 18, 2024
    26
    @chanChristin 看来下次还要再长一个辈分才行了!😂

    @2Nfree 好的,抽空我试试。
    danhahaha
    danhahaha
    Mar 18, 2024
    27
    连续俩帖子把我震住了,态度如此诚恳,此子必成大器
    danbai
    danbai
    PRO
    Mar 19, 2024 via Android
    28
    哥们都用 golang 了你可以用用 rod 这个库
    eber
    eber
    OP
    Mar 20, 2024
    29
    @danbai 兄弟我来还愿了。经过这两天的体验,rod 库确实用起来比 chromedp 方便多了!
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   952 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 51ms · UTC 19:53 · PVG 03:53 · LAX 11:53 · JFK 14:53
    ♥ Do have faith in what you're doing.