小编典典

从Go程序内部调用源

go

为了娱乐并更好地学习Go,我正在尝试在Go中重新实现抗原。

问题是:source是shell内置函数,所以我不能用os/exec Commandfunction
调用它,因为它希望在中有可执行文件PATH

我怎样才能做到这一点?并且,是否有可能使sourcego程序内部的程序影响用户shell?


阅读 288

收藏
2020-07-02

共1个答案

小编典典

您可以直接在终端设备中编写命令。但是,要做到这一点,首先您需要知道哪个设备正在使用该用户。执行程序的脚本可能是解决方案。

#!/bin/bash
echo Running from foo script, pid = $$
go run foo.go `tty`

然后,程序必须将命令写入终端设备。

package main

import (
    "C"
    "fmt"
    "os"
    "syscall"
    "unsafe"
)

func main() {
    // Get tty path
    if len(os.Args) < 2 {
        fmt.Printf("no tty path\n")
        os.Exit(1)
    }
    ttyPath := os.Args[1]

    // Open tty
    tty, err := os.Open(ttyPath)
    if err != nil {
        fmt.Printf("error opening tty: %s\n", err.Error())
        os.Exit(2)
    }
    defer tty.Close()

    // Write a command
    cmd := "echo Hello from go, pid = $$\n"
    cmdstr := C.CString(cmd)
    cmdaddr := uintptr(unsafe.Pointer(cmdstr))
    for i := range []byte(cmd) {
        _, _, err := syscall.Syscall(syscall.SYS_IOCTL, tty.Fd(), syscall.TIOCSTI, cmdaddr+uintptr(i))
        if uintptr(err) != 0 {
            fmt.Printf("syscall error: %s\n", err.Error())
            os.Exit(3)
        }
    }
}

这是示例输出:

$ echo $$
70318
$ ./foo 
Running from foo script, pid = 83035
echo Hello from go, pid = $$
$ echo Hello from go, pid = $$
Hello from go, pid = 70318

请注意,我使用./not 来执行脚本source,因此脚本的PID有所不同。但是后来,go程序执行的命令具有相同的PID。

2020-07-02