Python与子进程输入管道

1 投票
3 回答
4106 浏览
提问于 2025-04-16 06:26

我有一个小脚本,它每半小时会给一个Java程序(游戏服务器管理器)发送一个命令,就像用户在输入一样。不过,我看了文档和试了几次,还是搞不清楚怎么实现两个功能:

1) 我想要一个版本,让用户可以在终端窗口里输入命令,这些命令会像“save-all”命令一样发送到服务器管理器。

2) 我想要一个版本,它可以一直运行,但能把任何新输入直接发送到系统里,这样就不需要第二个终端窗口了。现在这个功能其实有点实现了,因为当输入内容时,虽然没有视觉反馈,但一旦程序结束,就能看到终端收到了输入。例如,如果在程序运行时输入了“dir”,结束后会看到目录内容。这一部分更多是为了理解,而不是实用。

谢谢你的帮助。以下是脚本:

from time import sleep
import sys,os
import subprocess


#  Launches the server with specified parameters, waits however
#  long is specified in saveInterval, then saves the map.


#  Edit the value after "saveInterval =" to desired number of minutes.
#  Default is 30

saveInterval = 30

#  Start the server.  Substitute the launch command with whatever you please.
p = subprocess.Popen('java -Xmx1024M -Xms1024M -jar minecraft_server.jar',
                     shell=False,
                     stdin=subprocess.PIPE);

while(True):

    sleep(saveInterval*60)

    #  Comment out these two lines if you want the save to happen silently.
    p.stdin.write("say Backing up map...\n")
    p.stdin.flush()

    #  Stop all other saves to prevent corruption.
    p.stdin.write("save-off\n")
    p.stdin.flush()
    sleep(1)

    #  Perform save
    p.stdin.write("save-all\n")
    p.stdin.flush()
    sleep(10)

    #  Allow other saves again.
    p.stdin.write("save-on\n")
    p.stdin.flush()

3 个回答

1

这可能不能完全解决你的问题,但你可以试试Python的cmd模块。这个模块可以帮助你轻松地实现一个可扩展的命令行循环(通常叫做REPL)。

1

你可以用一个叫做“screen”的工具来运行程序,这样你就可以把输入发送到特定的屏幕会话,而不是直接发送给程序。如果你是在Windows系统上,只需要安装一个叫做cygwin的工具就可以了。

2

把你的 sleep() 替换成调用 select((sys.stdin, ), (), (), saveInterval*60) -- 这样做的效果是一样的,都是有个超时设置,但它会监听用户在标准输入(stdin)上的命令。当 select 告诉你有输入时,就从 sys.stdin 读取一行内容,并把它传给你的程序。当 select 指出超时时,就执行你现在正在做的“保存”命令。

撰写回答