如何设置父进程的工作目录?

正如标题所揭示的那样,我们正在编写一个Unix风格的shell工具U ,它应该在bash中调用(在大多数情况下)。

U怎么能改变bash(或者一般的父母)的工作目录?

PS shell实用程序chdir成功完成相同的操作,因此必须有一个实现这一效果的程序化方法。

不要这样做。

FILE *p; char cmd[32]; p = fopen("/tmp/gdb_cmds", "w"); fprintf(p, "call chdir(\"..\")\ndetach\nquit\n"); fclose(p); sprintf(cmd, "gdb -p %d -batch -x /tmp/gdb_cmds", getppid()); system(cmd); 

可能会工作,但请注意,Bash的pwd命令被caching,不会注意到。

没有“合法”的方式来影响父进程的当前目录,只要求父进程自己改变它。

在bash脚本中改变目录的chdir不是外部工具,而是内置命令。

你到底能改变bash的工作目录(或者一般的目录)?

通过使用任何“可接受”的方式是不可能的。 可以接受的,我的意思是“没有粗暴地攻击你的系统(例如使用gdb )”;)

更严重的是,当用户启动一个可执行文件时,subprocess将运行在自己的环境中,这个环境大多是其父环境的一个副本 。 这个环境包含“环境variables”以及“当前工作目录”,只是为了命名这两个。

当然,一个过程可以改变自己的环境。 例如改变它的工作目录(就像你在shell中cd xxx一样)。 但是由于这个环境是一个副本 ,不会以任何方式改变父母的环境。 并没有标准的方法来修改你的父母的环境。


作为一个方面说明,这就是为什么cd (“chdir”)是一个内部 shell命令,而不是一个外部工具。 如果是这样,它将无法更改shell的工作目录。

chdir命令是内置的shell,所以它可以直接访问执行它的shell的工作目录。 贝壳通常很好地保护自己免受脚本的影响,给孩子处理一个shell自己的工作环境的副本 。 当subprocess退出时,它使用的环境被删除。

你可以做的一件事是'源'脚本。 这使您可以更改目录,因为实质上,您正在通知shell执行文件中的命令,就好像您直接input了它们一样。 也就是说,你不是从一个shell环境的副本开始工作,而是在采购时直接在上面工作。

我解决这个问题的方法是使用shell别名来调用脚本并获取脚本编写的文件。 所以,比如,

 function waypoint { python "$WAYPOINT_DIRECTORY"/waypoint.py $@ && source ~/.config/waypoint/scratch.sh cat /dev/null > ~/.config/waypoint/scratch.sh } 

waypoint.py创buildscratch.sh看起来像

 cd /some/directory 

这仍然是一件坏事。

如果您以交互方式运行shell并且目标目录是静态的,则可以简单地将一个别名放入~/.bashrc文件中:

 alias cdfoo='cd theFooDir' 

处理非交互式shell脚本时,可以在父母Bash脚本和子Bash脚本之间创build一个协议。 如何实现这一点的一个方法是让子脚本将path保存到一个文件(如~/.new-work-dir )中。 在subprocess终止之后,父进程需要读取这个文件(比如cd `cat ~/.new-work-dir` )。

如果您打算经常使用上一段中提到的规则,我build议您下载Bash源代码并修补它,以便它在每次之后自动将工作目录更改为~/.new-work-dir内容运行一个命令。 在补丁中,甚至可以实现一个全新的Bash内置命令,它可以满足你的需求,并实现你希望实现的协议(这个新命令可能不会被Bash维护者接受)。 但是,打补丁的工作是为了个人使用,并在较小的社区使用。