各位爹,请教一个 golang 的问题! - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
eber
V2EX    Go 编程语言

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

  •  
  •   eber 2024-03-18 10:20:12 +08:00 3460 次点击
    这是一个创建于 571 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    @2Nfree 好的,抽空我试试。
    danhahaha
        27
    danhahaha  
       2024-03-18 19:04:05 +08:00
    连续俩帖子把我震住了,态度如此诚恳,此子必成大器
    danbai
        28
    danbai  
    PRO
       2024-03-19 08:53:16 +08:00 via Android
    哥们都用 golang 了你可以用用 rod 这个库
    eber
        29
    eber  
    OP
       2024-03-20 10:08:13 +08:00
    @danbai 兄弟我来还愿了。经过这两天的体验,rod 库确实用起来比 chromedp 方便多了!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5466 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 06:41 PVG 14:41 LAX 23:41 JFK 02:41
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86