首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >运行脚本以发送游戏中的Terraria服务器命令

运行脚本以发送游戏中的Terraria服务器命令
EN

Stack Overflow用户
提问于 2020-04-21 06:29:43
回答 1查看 566关注 0票数 1

在过去的一周里,我在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编写的用于发送命令的代码:

代码语言:javascript
运行
复制
import subprocess

subprocess.Popen("terrariad save", shell=True)

这可以很好地工作,但是如果我尝试输入一个带空格的字符串:

代码语言:javascript
运行
复制
import subprocess

subprocess.Popen("terrariad \"say something\"", shell=True)

它在空格char中停止命令,在终端上输出以下内容:

代码语言:javascript
运行
复制
: say

而不是期望的:

代码语言:javascript
运行
复制
: say something
<Server>something

我能做些什么来解决这个问题?我尝试了那么多东西,但我得到了同样的结果。

附注:如果我在ssh putty终端中手动发送命令,它可以工作!

编辑1:

我放弃了python的解决方案,现在我将用bash来尝试它,似乎更符合逻辑地这样做。

编辑2:

我发现"terrariad“脚本只期望一个参数,但是Popen将我的参数一分为二,不管我使用什么方法,因为我的输入字符串中间有一个空格字符。如下所示:

期望值:

代码语言:javascript
运行
复制
terrariad "say\ something"

$1 = "say something"

但我对python Popen有这样的理解:

代码语言:javascript
运行
复制
subprocess.Popen("terrariad \"say something\"", shell=True)

$1 = "say
$2 = something"

不管我试着列出它:

代码语言:javascript
运行
复制
subprocess.Popen(["terrariad", "say something"])

$1 = "say
$2 = something"

或者在空格字符之前使用\ quote,如果到达空格字符,它总是拆分变量。

编辑3:

查看bash脚本,我可以理解当我发送命令时发生了什么……基本上,它使用screen程序中的"stuff“命令将字符发送到terraria screen会话:

代码语言:javascript
运行
复制
screen -S terraria -X stuff $send

$send是一个printf命令:

代码语言:javascript
运行
复制
send="`printf \"$*\r\"`"

在我看来,如果我从Python运行bash文件,它会得到与从命令行运行不同的结果。这怎么可能呢?这是一个bug还是该函数的错误实现?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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:

代码语言:javascript
运行
复制
mkfifo cmdOutput

*/ samba /terraria -这是我创建的目录,以便使用与samba (https://linuxize.com/post/how-to-install-and-configure-samba-on-ubuntu-18-04/)共享的其他计算机轻松编辑脚本、保存地图并将其加载到服务器

然后,我创建了一个python脚本来读取屏幕输出,然后写入管道文件(我知道,可能还有其他方法):

代码语言:javascript
运行
复制
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获取),并将错误重定向到另一个文件:

代码语言:javascript
运行
复制
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服务器备份它,如果我有时间做其他事情,让终端显示服务器正在发生的事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61333122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档