通过/ proc / {pid} / fd / 0使用stdin向java -jar发送命令

我正在尝试使用/ proc / {pid} / fd / 0向Minecraft服务器jar发送命令,但服务器不执行该命令.

要复制我正在尝试做的事情,你可以在基于Debian的机器上执行此操作(可能还有其他Linux分发).

我用它来测试这个:

> Ubuntu 14.04
> minecraft_server.jar(用1.8测试)
> OpenJDK运行时环境(使用default-jre-headless安装)

第一个控制台

$java -jar minecraft_server.jar nogui

回复:[…服务器启动并等待输入]

say hi

回复:[19:52:23] [服务器线程/信息]:[服务器]嗨

第二控制台:

现在,当我切换到第二个控制台时,服务器仍然在第一个i中运行:

echo "say hi2" >> /proc/$(pidof java)/fd/0

一切顺利,直到我切换回第一个控制台.我可以看到文字“说hi2”,但服务器还没有认出来.我可以再次在第一个控制台中编写另一个命令,就好像从第二个控制台输入的文本甚至都不存在.

为什么是这样?更重要的是,如何以正确的方式使用/ proc / {pid} / fd / 0将命令发送到java jar文件?

我不知道这是否是某种我不知道的Java事物,如果我可以在执行服务器时使用某些标志或某些东西,或者它是服务器jar本身就是问题.

我知道你可以使用screen,tail -f或某种服务器包装来实现这一目标,但这不是我所追求的.我想以某种方式使用此方法发送命令.

解决方法:

这不是Java的事情.你在尝试的是根本不可行的.

像这样测试:

控制台1:

 $cat

一旦你点击“返回”,这基本上会回显你在它上面输入的任何内容.

Console2:查找cat命令的进程号.让我们说它是NNN.做:

$echo Something > /proc/NNN/fd/0

切换回Console1.你会在控制台输出上看到“Something”,但它没有回应.

为什么?做

$ls -l /proc/NNN/fd

你可能会理解.所有三个描述符,0表示stdin,1表示stdout,2表示stderr实际上是符号链接,并且都指向相同的伪终端从属(pts)设备,这是与您的第一个终端相关联的pts.

所以基本上,当你写它时,你实际上写入控制台输出,而不是它的输入.如果您从该文件中读取,您可以窃取一些应该在第一个控制台中进入该进程的输入(您正在竞争此输入).这就是角色设备的工作方式.

/ proc的文档说:

/proc/[pid]/fd/

This is a subdirectory containing one entry for each file
which the process has open, named by its file descriptor, and
which is a symbolic link to the actual file. Thus, 0 is
standard input, 1 standard output, 2 standard error, and so
on.

所以这些不是该过程打开的实际文件描述符.它们只是指向文件(或者在本例中为字符设备)的链接,其名称指示它们在给定进程中附加到哪个描述符.他们的主要职责是告诉您该进程是重定向其文件描述符还是已打开任何新文件描述符,以及它们指向哪些资源.

但是如果你想要另一种方法,你可以使用fifo – 一个命名管道.

通过执行以下操作创建fifo:

$mkfifo myfifo

运行你的java程序:

$java -jar minecraft_server.jar nogui < myfifo

打开另一个控制台写

$cat > myfifo

现在开始输入东西.切换到第一个控制台.您将看到您的服务器正在执行您的命令.

但要注意你的文件结尾.有几个进程可以写入同一个fifo,但是一旦最后一个进程关闭它,你的服务器就会在其标准输入上收到一个EOF.

上一篇:java – 有没有办法将数据附加到Bukkit ItemStack?


下一篇:java – 关于resultset.getObject的AbstractMethodError