我经常使用此命令在我的开发虚拟机中切换用户:
✸ sudo su - otheruser
但是,如果我尝试访问/dev/stderr
或类似操作,我会遇到麻烦:
otheruser$ echo hi > /dev/stderr
-bash: /dev/stderr: Permission denied
我知道我可以>&2
在这个特定实例中使用它,但在某些情况下(例如tee /dev/stderr
)您需要一个可打开的文件,而不仅仅是一个文件描述符。
我发现我可以在 sudo 之前在 tty 上打开写权限来解决这个问题:
✸ ls -ld /dev/stderr
lrwxrwxrwx 1 root root 15 Jan 13 08:06 /dev/stderr -> /proc/self/fd/2
✸ ls -ld /proc/self/fd/2
lrwx------ 1 aron aron 64 Jan 14 15:08 /proc/self/fd/2 -> /dev/pts/13
✸ ls -ld /dev/pts/13
crw--w---- 1 aron tty 136, 13 Jan 14 15:08 /dev/pts/13
✸ chmod a+w /dev/pts/13
或者更简单地说:
✸ chmod a+w /dev/stderr
但我想知道我是否应该使用其他调用,以便正确分配和/或授予权限。有什么建议吗?
答案1
这是 Linux 实现 /proc 的一个已知怪癖;从未修复多年来。在 Linux 中,打开下面的链接/proc/*/fd/*
不会像 dup() 那样直接复制文件描述符(尽管神奇的 /proc 链接可以理论上实现这一点)——相反,它会重新打开文件,并执行新的权限检查。
您发现的最基本的解决方法是在使用su
或之前授予目标用户对您的 tty 的权限sudo
。例如:
userA$ setfacl -m u:userB:rw /dev/stderr
userA$ sudo -i -u userB
(也许可以编写一个具有同样功能的 PAM 模块。)
一个可能更好的解决方法是使用用户切换方法,为你提供一个全新的 tty——su --pty
如果你有 su 的 util-linux 版本,那么就有这样的工具。Systemd 有一个systemd-run
工具可以运行临时服务交互地;同样,它带有一个machinectl shell
主要用于容器的工具,但最近的版本还有“环回”模式:
userA$ sudo su -l -P userB
userA$ sudo systemd-run --uid=userB --shell --quiet --collect
userA$ sudo machinectl shell userB@
你也可以得到与使用相同的结果终端多路复用器例如 Screen 或 tmux,它们必须为其窗口/窗格分配新的 tty:
userA$ sudo -u userB tmux
所有这些工具都会为嵌套会话分配一个新的 pty,在双方之间中继所有输入/输出。