从Go更改父Shell目录

时间:2018-12-31 07:40:05

标签: go

我如何编写一个与cd一样的Go程序?

我尝试运行命令,但是没有用。

func main() {
    cmd := exec.Command("cd", "/media/")
    err := cmd.Run()
    log.Printf("Command finished with error: %v", err)
}

1 个答案:

答案 0 :(得分:5)

  

我如何编写一个与cd一样的Go程序?

这在POSIX系统上不可能 (即使使用其他编程语言也是如此)。

因为每个process(包括父shell进程)都具有自己的 own 当前working directory。因此cd必须是shell builtin(调用chdir(2)系统调用由shell进程本身完成),它不能由某些executable完成,因为shell会分叉a运行每个命令的新过程(使用一些可执行文件,即不是内置文件)。

阅读一些不错的Unix或Linux编程书籍,例如ALP,以获得解释。一本关于Operating systems的好书,例如Operating systems: three easy pieces会向您解释为什么会这样(并且在类似POSIX或类Unix的系统中不可能这样)。

您的代码是forking(带有cmd.Run)的新进程,并且 子进程正在更改其工作目录。另请参见fork(2)execve(2)path_resolution(7)

要在Go代码中调用chdir(2)系统调用,请使用os.Chdir。那只会影响您的流程(以及fork(2)创建的所有将来的子流程,它们都继承其父流程的工作目录),当然不会更改您的父流程的工作目录(通常是您的shell) )。

要获取当前进程的当前工作目录(通过getcwd(2)系统调用),请在Go代码中使用os.Getwd(并查看this)。

在Linux上,您可以使用/proc/(有关详细信息,请参见proc(5))来查询其他进程的工作目录。例如,在您的Shell中运行ls -l /proc/$$/cwd。在Go代码中,您将在/proc/1234/cwd等路径上使用os.Readlink。当然,您不能更改其他进程的工作目录(唯一可以更改的工作目录是您自己的过程,使用chdir(2)

根据David Budsworth的评论,您可以采用一种奇怪的惯例:1.您的prog程序在以下位置写入有效的目录路径(并在外壳程序中适当引用):标准输出,仅此而已。 2.您总是将prog程序与command substitution一起使用,例如cd $(prog args...)(可能成为shell function或{ {3}}等),那么您的外壳程序(而不是prog)将更改程序输出的目录。