在过去的一周里,我在Ubuntu v18.04操作系统上安装了一台Terraria 1.3.5.3服务器,用于与朋友在线游戏。此服务器应全天候通电,不需要任何GUI,仅可通过内部LAN上的SSH访问。
我的朋友问我是否有办法控制服务器,例如通过内部游戏聊天发送消息,所以我想在想要的命令(例如‘$say something’或'$save‘)前面使用一个特殊字符($)和一个python程序,它通过管道读取终端输出,解释命令并将其与bash命令一起发送回来。
我按照以下说明安装服务器:
https://www.linode.com/docs/game-servers/host-a-terraria-server-on-your-linode
并将我的路由器配置为将专用端口转发到terraria服务器。
一切都很好,但我真的很难让python通过上面的链接中描述的"terrariad“bash脚本发送命令。
以下是用python编写的用于发送命令的代码:
import subprocess
subprocess.Popen("terrariad save", shell=True)
这可以很好地工作,但是如果我尝试输入一个带空格的字符串:
import subprocess
subprocess.Popen("terrariad \"say something\"", shell=True)
它在空格char中停止命令,在终端上输出以下内容:
: say
而不是期望的:
: say something
<Server>something
我能做些什么来解决这个问题?我尝试了那么多东西,但我得到了同样的结果。
附注:如果我在ssh putty终端中手动发送命令,它可以工作!
编辑1:
我放弃了python的解决方案,现在我将用bash来尝试它,似乎更符合逻辑地这样做。
编辑2:
我发现"terrariad“脚本只期望一个参数,但是Popen将我的参数一分为二,不管我使用什么方法,因为我的输入字符串中间有一个空格字符。如下所示:
期望值:
terrariad "say\ something"
$1 = "say something"
但我对python Popen有这样的理解:
subprocess.Popen("terrariad \"say something\"", shell=True)
$1 = "say
$2 = something"
不管我试着列出它:
subprocess.Popen(["terrariad", "say something"])
$1 = "say
$2 = something"
或者在空格字符之前使用\ quote,如果到达空格字符,它总是拆分变量。
编辑3:
查看bash脚本,我可以理解当我发送命令时发生了什么……基本上,它使用screen程序中的"stuff“命令将字符发送到terraria screen会话:
screen -S terraria -X stuff $send
$send是一个printf命令:
send="`printf \"$*\r\"`"
在我看来,如果我从Python运行bash文件,它会得到与从命令行运行不同的结果。这怎么可能呢?这是一个bug还是该函数的错误实现?
谢谢!
发布于 2020-05-03 23:42:44
我最终提出了一个解决方案,使用管道而不是Popen解决方案。
在我看来,Popen不是运行bash脚本的最佳解决方案,正如SiHa在评论中发送的链接How to do multiple arguments with Python Popen?中所描述的那样(谢谢!):
但是,使用Python作为许多系统命令的包装器并不是一个好主意。至少,您应该将命令分解为单独的Popen,以便可以充分处理非零出口。实际上,此脚本似乎更适合作为shell脚本。
所以我提出了一个解决方案,使用一个fifo文件:
首先,在所需目录(例如/samba/terraria/config)中创建一个用作管道的fifo:
mkfifo cmdOutput
*/ samba /terraria -这是我创建的目录,以便使用与samba (https://linuxize.com/post/how-to-install-and-configure-samba-on-ubuntu-18-04/)共享的其他计算机轻松编辑脚本、保存地图并将其加载到服务器
然后,我创建了一个python脚本来读取屏幕输出,然后写入管道文件(我知道,可能还有其他方法):
import shlex, os
outputFile = os.open("/samba/terraria/config/cmdOutput", os.O_WRONLY )
print("python script has started!")
while 1:
line = input()
print(line)
cmdPosition = line.find("&")
if( cmdPosition != -1 ):
cmd = slice(cmdPosition+1,len(line))
cmdText = line[cmd]
os.write(outputFile, bytes( cmdText + "\r\r", 'utf-8'))
os.write(outputFile, bytes("say Command executed!!!\r\r", 'utf-8'))
然后,我编辑terraria.service文件以调用此脚本(通过管道从terrariaServer获取),并将错误重定向到另一个文件:
ExecStart=/usr/bin/screen -dmS terraria /bin/bash -c "/opt/terraria/TerrariaServer.bin.x86_64 -config /samba/terraria/config/serverconfig.txt < /samba/terraria/config/cmdOutput 2>/samba/terraria/config/errorLog.txt | python3 /samba/terraria/scripts/allowCommands.py"
*/samba/terraria/scripts/allowCommands.py -脚本所在的位置。
**/samba/terraria/config/errorLog.txt -将错误日志保存到文件中。
现在我可以发送命令,比如'noon‘或'dawn’,这样我就可以改变游戏中的时间,拯救世界,并在老板比赛之前用samba服务器备份它,如果我有时间做其他事情,让终端显示服务器正在发生的事情。
https://stackoverflow.com/questions/61333122
复制相似问题