python - 运行脚本以发送游戏内泰拉瑞亚服务器命令

标签 python bash ubuntu

在过去的一周里,我在 Ubuntu v18.04 操作系统中安装了 Terraria 1.3.5.3 服务器,用于和 friend 在线玩。此服务器应 24/7 开机,没有任何 GUI,只能通过内部 LAN 上的 SSH 访问。

我的 friend 问我是否有办法让他们控制服务器,例如通过内部游戏内聊天发送消息,所以我想在所需命令(例如'$say something'或'$save')和读取通过管道终端输出,解释命令并使用 bash 命令将其发送回。

我按照以下说明安装服务器:

https://www.linode.com/docs/game-servers/host-a-terraria-server-on-your-linode

并配置我的路由器以将专用端口转发到泰拉瑞亚服务器。

一切正常,但我真的很难让 python 通过上面链接中描述的“terrariad”bash 脚本发送命令。

这是用于在 python 中发送命令的代码:

import subprocess

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

这很好用,但是如果我尝试输入带空格的字符串:

import subprocess

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

它在空格字符中停止命令,在终端上输出:
: 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"

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

编辑3:

查看 bash 脚本,我可以理解当我发送命令时发生了什么......基本上它使用来自屏幕程序的命令“stuff”将字符发送到 terraria 屏幕 session :

screen -S terraria -X stuff $send

$send 是一个 printf 命令:

send="`printf \"$*\r\"`"

在我看来,如果我从 Python 运行 bash 文件,它的结果与从命令行运行的结果不同。这怎么可能?这是功能的错误还是错误的实现?

谢谢!

最佳答案

我终于有了一个解决方案,使用管道而不是 Popen 解决方案。

在我看来,Popen 并不是运行 bash 脚本的最佳解决方案,如 How to do multiple arguments with Python Popen? 中所述。 ,SiHa 在评论中发送的链接(谢谢!):

“但是,使用 Python 作为许多系统命令的包装器并不是一个好主意。至少,您应该将命令分解为单独的 Popen,以便可以充分处理非零退出。实际上,这script 似乎更适合作为 shell 脚本。”。

所以我提出了解决方案,使用了一个 fifo 文件:

首先,在所需目录(例如,/samba/terraria/config)中创建一个用作管道的 fifo:

mkfifo cmdOutput

*/samba/terraria - 这是我创建的目录,以便使用另一台计算机轻松编辑脚本、保存和加载 map 到服务器,与 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 - 将错误日志保存在文件中。

现在我可以发送命令,比如“中午”或“黎明”,这样我就可以更改游戏时间、保存世界并在老板打架之前用 samba 服务器备份它,如果我有时间可以做其他事情 XD,并拥有终端显示服务器正在发生的事情。

关于python - 运行脚本以发送游戏内泰拉瑞亚服务器命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61333122/

相关文章:

python - Linux 服务器上的 HTTP 错误 429,但不是我的本地计算机?

bash - 在 bash 脚本中使用空格拆分句子

python - 日志文件的正则表达式

python在windows中调用汉字命令行失败

bash - 仅替换文件中大括号外的字符串

linux - Bash 文件在用于 testng 的 Windows 中运行良好,但在 linux/mac 中不起作用

python脚本输出保存在不同的文件夹中

ubuntu - 将 Ubuntu 迁移到另一个平台时如何保留已安装的应用程序?

python - Cherrypy 3.2 虚拟主机调度程序

python - 函数作为 Python 中的对象 : what exactly is stored in memory?