如何记录正在运行的进程的实时输出

时间:2019-06-23 11:17:17

标签: linux bash pipe

我想在Ubuntu机器中运行游戏服务器。我想在后台运行它,并将该进程的实时输出写入日志文件。我尝试使用nohup,最后使用“&”运行游戏服务器,但是我无法使其按我想要的方式工作。

然后,我开始阅读有关命名管道的内容,并实际尝试了一下。我编写了一个简单的脚本,理论上应该可以使用。但是,我当然会丢失一些东西。

首先,我使用mkfifo命令制作了一个管道。

mkfifo testpipe

然后我创建了一个小脚本:

#!/bin/bash
./mta-server64 > pipe &

pid=$!

echo $pid // so I know the pid of the process

cat < pipe > log.txt &

(注意:我是从内存中编写此代码的。)

该代码仅在出现错误并且过程停止时起作用。它实际上记录了游戏机错误。但是当游戏服务器运行时,日志文件中没有输出。

我想读取在后台运行的进程的输出(如果没有记错的话,请输入stdout和stderr),并将其记录在日志文件中。

我还考虑过使用屏幕,因为它会将所有内容记录在文件中,但是如果有更好的解决方案,我宁愿不使用它。

编辑:

首先:谢谢您对帮助我的兴趣。同样,对于仅提供有关此小型项目的详细信息,以及对stdout和stderr的了解有限,我必须道歉。

我们先去一垒。

我想运行一个名为Multi Theft Auto(https://multitheftauto.com/)的游戏服务器。这是GTA圣安地列斯,但是多人游戏。

我可以通过调用可执行文件./mta-server-64在Ubuntu服务器中轻松运行此游戏服务器。调用后,游戏服务器控制台出现:

[|] MTA: San Andreas :: 0/32 players :: 196 resources :: 125 fps (25)
MTA:BLUE Server for MTA:SA
==================================================================
= Multi Theft Auto: San Andreas v1.5.6 [64 bit]
==================================================================
= Server name      : Default MTA Server
= Server IP address: auto
= Server port      : 22884
=
= Log file         : /root/mta/mods/deathmatch/logs/server.log
= Maximum players  : 32
= HTTP port        : 22564
= Voice Chat       : Disabled
= Bandwidth saving : Medium
==================================================================
[09:49:07] Resource 'mapmanager' requests some acl rights. Use the command 'aclrequest list mapmanager'
[09:49:07] Resources: 196 loaded, 0 failed
[09:49:07] Starting resources...
[09:49:07] Server minclientversion is now 1.5.6-9.16588.0
[09:49:07] INFO: MAPMANAGER: Some important ACL permissions are missing. To ensure the correct functioning of Mapmanager, please write: aclrequest allow mapmanager all
[09:49:07] Gamemode 'play' started.
[09:49:07] Authorized serial account protection is enabled for the ACL group(s): `Admin`  See http://mtasa.com/authserial
[09:49:07] WARNING: <owner_email_address> not set
[09:49:07] Server started and is ready to accept connections!
[09:49:07] To stop the server, type 'shutdown' or press Ctrl-C
[09:49:07] Type 'help' for a list of commands.
[09:49:07] Querying MTA master server... success! (Auto detected IP:xxx.xxx.xxx.xxx)

我正在使用以下脚本在后台运行该过程,并(尝试)从以下位置获取实时输出:

#!/bin/bash

newport=$(shuf -i 22003-22900 -n 1)
newip=$(shuf -i 22003-22900 -n 1)

rm -rf ~/server/*

cp -r /home/user*/ftp/server/mtaserver/serverfiles/* ~/server

sed -i "s/<httpport>[0-9][0-9][0-9][0-9][0-9]<\/httpport>/<httpport>$newport<\/httpport>/g" ~/server/mods/deathmatch/mtaserver.conf
sed -i "s/<serverport>[0-9][0-9][0-9][0-9][0-9]<\/serverport>/<serverport>$newip<\/serverport>/g" ~/server/mods/deathmatch/mtaserver.conf

~/server/mta-server64 2>&1 | tee -a outfile &

mta_pid=$!

echo $mta_pid

sleep 6

pkill $mta_pid

(注意:由于某些技术问题,我不得不添加脚本的前几行,这些脚本会自动用新文件替换游戏文件,并用随机文件替换现有端口。)

此脚本启动服务器,并尝试记录该进程的输出。几秒钟后,该过程将自动终止,因此在任何给定时间只有一个游戏服务器实例。

问题:

此脚本仅在出现错误时记录输出。当它仍在运行时,我仍然无法获得该过程的实时输出。也许这是游戏服务器的问题,但我真正相信应该有一种方法可以使它按我预期的方式工作。

3 个答案:

答案 0 :(得分:2)

我相信您想使用tee命令将管道输出拆分为日志文件。

我建议您阅读article和这些答案1 2

答案 1 :(得分:1)

nohup somecommand > somecommand.log 2>&1 &通常足以tail -F somecommand.log来跟踪日志。

答案 2 :(得分:0)

两天后,我终于找到了一种使其工作的方式(我打算工作的方式,而没有考虑任何重大的安全/性能风险)。

阅读评论使我意识到我在攻击错误的观点。游戏服务器的标准输出已缓冲,因此无法使用我发布问题时尝试的方法将其登录到日志文件中。至少这是我所了解的。

我做了一些关于如何在不缓冲标准输出的情况下运行应用程序的研究:https://serverfault.com/questions/294218/is-there-a-way-to-redirect-output-to-a-file-without-buffering-on-unix-linux

现在我的代码:

    stdbuf -o0 ~/server/mta-server64 >> pipe &

    cat < pipe | tee -a outfile &

创建命名管道后,它将在该管道内执行游戏服务器,然后将stdout附加到日志文件中。

stdbug -o0命令禁用标准输出缓冲(如上面的链接所述)。

这对我有用,我不能保证它对其他人也有用。我仍然不知道禁用缓冲是否是解决我的问题的安全方法,但现在是我所需要的。