我希望更改用户的进程,以便我可以设置它的 cwd。
相关的,以及中学对于这个问题,我有一个想要卸载的文件系统,但用户正在使用 bash 进程坐在它上面。我不想终止该用户的进程,但我想在卸载磁盘时轻轻地将它们重定向到.../tmp。
我显然是root。
答案1
没有办法从进程外部更改其工作目录,无论是否为 root。这会对受害者进程造成极大的干扰,而且没有相应的 API。
现在你可以使用肮脏的伎俩了。其中之一是将调试器附加到目标进程,并强制执行chdir
- 请参阅Stack Overflow 上的这个问题。某些操作系统可能会提供其他 API 来执行此类任务(在毫无戒心的进程中注入系统调用)。
至于您从某人下重新安装文件系统的目标,这基本上是没有希望的,即使您在技术上设法破解它 - 很可能该进程将在“旧”安装上打开文件描述符,并且没有可移植的方法来正确地重新安装- 将它们附加到“新”安装上的文件,即使相应的文件仍然存在。
理论上似乎可行的方法是休眠您想要的进程,以使其不妨碍维护。但这存在很多问题,特别是不仅考虑到普通文件,还考虑到网络套接字。 (看这另一个问题一些有趣的观点。)
简而言之,你最好有礼貌kill
(有宽限期),没有人知道在cwd
随机过程中玩游戏会产生什么意想不到的后果。
答案2
进程负责管理自己的当前目录。没有办法从外部改变它。
您可以通过让进程更改其自己的目录来作弊。如果您以 root 身份运行,或者以与进程相同的用户身份运行,则可以使用ptrace
系统调用对进程执行各种侵入性操作,包括在其鼻子底下更改内存和执行系统调用。这就是调试器所使用的。
将其视为实验性外科手术。患者可能会毫发无伤地醒来或死亡。如果进程并不真正关心其当前目录是什么,那么这应该可行。与其当前目录有密切关系的程序(例如 shell)不太可能生存。
这是我过去用来将进程从挂起的 NFS 挂载中移出的脚本。使用风险自负。
#!/bin/sh
if [ $# -ne 2 ]; then
echo 1>&2 "Usage: $0 PID DIR"
exit 120
fi
case "$1" in
*[!0-9]*) echo 1>&2 "Invalid pid \`$1'"; exit 3;;
esac
case "$2" in
*[\\\"]*)
echo 1>&2 "Unsupported character in directory name, sorry."
exit 3;;
esac
gdb -n -pid "$1" -batch -x /dev/stdin <<EOF
call chdir("$2")
detach
quit
EOF