2010-11-02 129 views
1

我有一個小腳本啓動,並且每半個小時向java程序(遊戲服務器管理器)提供一個命令,就好像用戶正在鍵入它一樣。但是,在閱讀文檔和試驗之後,我無法弄清楚我如何得到兩件東西:Python和子流程輸入管道

1)允許用戶將命令鍵入終端windoe並將它們發送到服務器管理器輸入的版本就像「全部保存」命令一樣。

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() 

回答

2

用一個對select((sys.stdin,),(),(), saveInterval*60)的調用替換你的sleep() - 它將有相同的超時時間,但在stdin上監聽用戶命令。當select表示您有輸入時,請從sys.stdin中讀取一行並將其提供給您的進程。當select表示超時時,請執行您現在正在執行的「保存」命令。

+0

太棒了,我還沒有聽說過這個。謝謝。 – Sean 2010-11-04 04:05:43

+0

作爲一個警告 - 你沒有提到你在哪個平臺上 - 'select'可能無法在win32上正常工作。我只熟悉* nix。 – bstpierre 2010-11-04 14:33:52

1

它不會徹底解決你的問題,但你可能會發現Python的cmd模塊有用。這是一種輕鬆實現可擴展命令行循環(通常稱爲REPL)的方式。

+0

我可能會嘗試重構這一點,在這種情況下cmd可能非常有用。感謝您的建議。 – Sean 2010-11-04 04:06:18

1

您可以使用屏幕運行程序,然後您可以將輸入發送到特定的屏幕會話,而不是直接發送到程序(如果您在Windows中,只需安裝cygwin)。