我有两个由两个不同用户运行的进程。这两个用户都属于同一组。我想stdin
通过写入 从一个进程写入/proc/<pid>/fd/0
,但权限仅为另一个用户设置,因此我得到的是permission denied
。我能否以某种方式更改权限,以便另一个进程可以写入它?
$ ls -lsa /proc/<pid>/fd/
0 lrwx------ 1 foo group1 64 Feb 14 23:15 0 -> /dev/pts/3
答案1
0 lrwx------ 1 foo group1 64 Feb 14 23:15 0 -> /dev/pts/3
我是否可以以某种方式改变权限以便其他进程可以写入它?
是的,但是写作可能不会达到你想要的效果。
/dev/pts/3
是伪终端从属设备。您跟踪的进程从伪终端获取输入。您可以使用 更改此类设备的权限chmod
。命名的节点0
不会反映更改,但/dev/pts/3
会。要使用更改的权限,您需要写入/dev/pts/3
,而不是0
。
但结果很可能不符合您的预期。为了解释这一点,请在终端仿真器(konsole
, xterm
)或终端多路复用器(tmux
, screen
)中运行 shell 并调用ls -l /proc/$$/fd/
。您会发现 shell 读取和写入相同的pts
。当它读取时,它会读取您输入的内容。当它写入时,它会让字符出现在终端中。
如果您写入/dev/pts/3
:也会发生相同的情况,终端中将出现字符,为相关进程提供输入。您的操作不会像在终端中键入一样注入输入,即它不会为进程提供输入。
要注入像您键入的那样的输入,您需要写入相应的主设备。这是 不简单。简而言之:
在 Linux 上,使用
devpts
,没有主设备文件。主端的进程使用通过打开 获得的文件描述符ptmx
,但没有相应的设备节点。
“主端上的进程”是终端仿真器、终端多路复用器sshd
(如果客户端请求伪终端)expect
……
然而另一个答案状态:
有一个特殊的 ioctl (
TIOCSTI
),它允许您将一个字节插入到 tty 的输入队列中,就好像它是从另一端接收的一样。TIOCSTI
只有当不在调用它的进程的控制 tty 上使用时,才会以 root 身份工作。
有关详细信息,请参阅完整答案。我猜这对您可能不是很有用,因为需要 root 访问权限。
(单向)连接两个进程的最简单方法是使用管道连接它们:
foo | bar
如果进程即将由两个不同的用户启动,请使用命名管道而不是未命名管道:
# any user
mkfifo pipeA
chmod … # allow access for the other user
# user1
foo >pipeA
# user2
<pipeA bar
命名管道的行为符合您的预期,而伪终端从属设备则不然。
注意foo
和bar
启动时各自的 stdout 和 stdin 已经重定向。正在运行的进程可以重定向自己的 stdin(例如 shell 可以根据需要重定向),但没有简单/优雅的方法来强制它。
例如,如果所讨论的进程是交互式的,则可以通过调用bash
使其将其 stdin 从重定向。然后,您可以从另一个控制台执行类似操作,并且 shell 将像您键入它一样执行(并且它可能会退出,因为写入管道的所有描述符现在都已关闭;为避免这种情况,请首先在 shell 中打开命名管道以进行写入:)。pipeA
exec 0<pipeA
echo date >pipeA
date
exec 0<>pipeA
答案2
一般来说,您无法写入标准输入。顾名思义,标准输入用于输入,而不是输出,即使它是一个常规文件,您也不能假设它已使用只读访问权限以外的任何方式打开。
听起来你试图做的是在另一个程序的输入上产生一个程序的输出,这通常只有在它们通过管道连接时才会起作用。如果你打开该文件描述符文件(如果允许),而不是创建到该进程现有标准输入的管道,你只会写入该进程的 TTY。该 TTY 的用户会对此非常不满,这就是为什么通常不允许这样做的原因。
可以通过连接管道来生成不同用户的进程,但通常需要 root 权限或具有该权限的程序的帮助(如sudo
)。
如果您需要在两个进程之间进行通信,但不能或不想使用管道,那么您可能想使用 Unix 套接字。一个进程应该打开套接字并对其进行侦听,然后其他进程可以打开套接字并连接到它,从而在两个进程之间创建双向通道。由于套接字位于文件系统中,因此您可以授予它权限,以便同一组的成员都可以使用它。