【问题标题】:Change parent shell directory from Go从 Go 更改父 shell 目录
【发布时间】:2019-05-27 19:59:18
【问题描述】:

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

我尝试运行命令,但没有成功。

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

【问题讨论】:

标签: go


【解决方案1】:

如何编写一个像 'cd' 一样的 Go 程序?

这在 POSIX 系统上是不可能的(即使使用任何其他编程语言)。

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

阅读一些好的 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 程序在标准输出上写入一个有效的(并为shell 适当引用)目录路径,没有别的了。 2. 你总是prog 程序与command substitution 一起使用,例如cd $(prog args...)(可能成为shell functionalias 的主体,等等...) ,那么你的shell(不是你的prog)会改变你的程序输出的目录。

【讨论】:

  • 谢谢,我实际上正在尝试实现书签程序,该程序将 cd 转换为转换为目录的“书签”名称,关于如何解决这个问题的任何想法?
  • 这是不可能的,除非你从你的程序中直接调用os.Chdir(并且不会改变父shell的工作目录,只有运行您的程序的进程及其所有未来的子进程)。同样,您需要阅读ALP。不可能有任何“解决方法”。
  • 好吧,解决方法是创建一个别名来运行列出路径的 go 程序。alias gcd=goprogram cd a
  • 这不是解决方法。你无法改变每个进程都有自己的工作目录这一事实,也无法改变其他进程(例如你的父 shell)的工作目录
  • 可以通过alias gcd=cd [backtick] goprog foo [backtick] 的别名来实现(不确定如何在cmets 中键入文字反引号,因为这会生成代码sn-p。但这将运行goprogfoo 作为一个参数,然后 cd 输出到任何输出
猜你喜欢
  • 1970-01-01
  • 2015-11-23
  • 2012-11-25
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多