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

244 天前
 eber

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

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

3061 次点击
所在节点    Go 编程语言
29 条回复
deplives
244 天前
sudo 可以使用 -S 从 stdin 传入密码
eber
244 天前
@lele140 虚心学习嘛 不磕碜!!!
chanChristin
244 天前
提问的艺术得更新了
2Nfree
244 天前
golang.org/x/crypto/ssh 包可以创建标准管道输出
用 session.StdinPipe()
2Nfree
244 天前
@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
244 天前
@chanChristin 看来下次还要再长一个辈分才行了!😂

@2Nfree 好的,抽空我试试。
danhahaha
244 天前
连续俩帖子把我震住了,态度如此诚恳,此子必成大器
danbai
243 天前
哥们都用 golang 了你可以用用 rod 这个库
eber
242 天前
@danbai 兄弟我来还愿了。经过这两天的体验,rod 库确实用起来比 chromedp 方便多了!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1024606

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX