无法从Go应用程序运行`op`

kiz8lqtg  于 2023-04-18  发布在  Go
关注(0)|答案(1)|浏览(94)

我正在尝试围绕1Password CLI可执行文件op编写一个小型Go Package 器应用程序,如下所示:

package main

import (
    "encoding/json"
    "log"
    "os/exec"
)

func main() {
    op := exec.Command("op", "item", "get", "DocSend", "--format=json")
    out, err := op.Output()
    if e, ok := err.(*exec.ExitError); ok {
        log.Fatal(e, ": ", string(e.Stderr))
    }

    var item map[string]interface{}
    if err := json.Unmarshal(out, &item); err != nil {
        log.Fatal(err)
    }
    println(item["fields"])
}

但是,我总是得到以下错误:

2023/04/13 09:48:51 exit status 1: [ERROR] 2023/04/13 09:48:51 error initializing client: connecting to desktop app: read: connection reset, make sure the CLI is correctly installed and Connect with 1Password CLI is enabled in the 1Password app

但是当我从Python脚本中做同样的事情时,如下所示:

#!/usr/bin/env python

import json
import subprocess

op = subprocess.run(["op", "item", "get", "DocSend", "--format=json"], capture_output=True)

item = json.loads(op.stdout)
print(item["fields"])

...我得到的输出很好:

[{'id': 'username', 'type': 'STRING', 'purpose': 'USERNAME', 'label': 'username', 'value': '...', 'reference': 'op://Shared/DocSend/username'}, {'id': 'password', ...}]

为什么不能从Go语言调用op命令?
更新:
有趣的是,当我从Go应用程序调用Python脚本时,它工作得很好。给定以下名为op.py的Python脚本:

#!/usr/bin/env python

import subprocess

subprocess.run(["op", "item", "get", "DocSend", "--format=json"])

和下面的Go应用程序在同一个目录中:

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "os/exec"
)

func main() {
    op := exec.Command("/usr/bin/python3.11", "./op.py")
    //op := exec.Command("op", "item", "get", "DocSend", "--format=json")
    out, err := op.Output()
    if e, ok := err.(*exec.ExitError); ok {
        log.Fatal(e, ": ", string(e.Stderr))
    }

    fmt.Printf("%s", out)

    var item map[string]interface{}
    if err := json.Unmarshal(out, &item); err != nil {
        log.Fatal(err)
    }
    fmt.Println(item["fields"])
}

我可以测试它是由Go应用程序而不是Python脚本打印的,因为如果我删除fmt.Printf(...)及其以下的代码,什么都不会打印出来。

cwtwac6a

cwtwac6a1#

我实际上使用GoLang作为一个覆盖的GUI应用程序,它作为一个集中控制器与几个不同的cpp二进制文件进行通信。我实现了以下函数来运行通用命令:

func RunCmd(binary string, cmd []string) []string {
    var output []string
    c, b := exec.Command(binary, cmd...), new(bytes.Buffer)
    c.Stdout = b
    c.Run()
    s := bufio.NewScanner(b)
    for s.Scan() {
        output = append(output, s.Text())
    }
    return output
}

此函数运行命令并将输出作为字符串切片返回(每行输出一个)。下面是调用它的示例:

_ = RunCmd("./moveRobot", []string{"10.20.0.37", localIP.String(), "align"})

在您的示例中,您可以将其称为:

out = RunCmd("op", []string{"item", "get", "DocSend", "--format=json"})

但是,您也可能需要提供op二进制文件的路径,因此我会尝试这样做(如果它在同一个目录中,则使用./op
这显然不会按原样返回JSON格式的输出,但您可以将其用作起点,至少确认调用正在工作。

相关问题