我有一些自主脚本,它们通过 ssh 在远程机器上运行命令。这些脚本依赖于获取 stdout、stderr 和每个命令运行的返回代码。我希望能够监控每个目标机器上的脚本进度,以便查看是否有问题挂起,并在必要时进行干预。
我最初的想法是让脚本在屏幕会话中运行命令,这样监控人员就可以简单地使用 附加到会话中screen -x
。但是,由于屏幕是一个交互式程序,因此很难从脚本中做到这一点。我可以使用 向屏幕会话发送命令screen -S session -X stuff "command^M"
,但这样我就得不到我需要的输出和返回代码。
我的第二个想法是将整个会话script /path/to/log
记录~/.bash_profile
到一个文件中。然后监控人员只需跟踪日志文件即可。然而,这并不能提供我想要的交互性。
关于如何解决这个问题有什么想法吗?
答案1
我使用 php 作为 shell 脚本来管理我的 Minecraft 服务器。我使用服务器日志来获取回复。这是我用来列出谁在线的代码。我用它来tail
获取最后几行并解析它们的时间,以确保响应是在我发送命令之后。
#!/usr/bin/php
<?php
function send_cmd( $command )
{
exec('screen -S minecraft -X stuff "`printf "\\r' . $command . '\\r"`"');
}
function who()
{
if (!is_running())
{
echo 'Server is not running.' . CRLF;
return 4;
}
// Get the current time and send the command
$before = time() - 1;
send_cmd('list');
// Wait for the server to provide a response
while(time() < $before + 5) {
sleep(0.25);
$result = exec('tail ' . __DIR__ . '/server.log | grep "\[INFO\] Connected players"');
$stamp = strtotime(substr($result, 0, 19));
if ($before <= $stamp)
break;
unset($result);
}
if (isset($result))
{
echo $result . CRLF;
echo 'Server responded in ' . ($stamp - $before) . ' seconds.' . CRLF;
return 0;
}
else
{
echo 'Server did not respond.' . CRLF;
return 4;
}
}
答案2
大量的人际交往......我建议:
- 部署Check_MK并设置其日志监控
- 将脚本输出传送到日志文件并让 Check_MK 监视错误
在这种情况下,只有出现问题时,人员才会收到警报。他们有机会通过 Web 界面查看日志消息,确认消息,以便团队中的其他人知道事情正在处理中,并根据问题的性质决定何时采取行动。
答案3
我建议使用“nohup”——这会将 stdout 输出到 nohup.out。您可以使用 nohup 来 bg 脚本并安全注销,它将继续运行。查看 man nohup 了解更多详细信息。
典型用法是 #> nohup /usr/local/bin/myscript.sh &
它将在后台运行脚本,并且不需要您保持登录状态。nohup.out 在运行时将位于当前工作目录中,如果权限不允许,则位于 $HOME/nohup.out 中。然后,您可以检查 nohup.out 的内容以查找需要解决的任何问题并进行相应的处理。
现在,为了解决您的交互性,您可以使用屏幕和 nohup 运行脚本,这样,如果进程挂起等待您的输入,您可以将该进程带回前台。
希望这可以帮助
答案4
如果您想使用屏幕,您可以尝试这样的操作:
ssh user@address screen -d -m <command>
参数-d -m
组合使屏幕开始一个新的会话但并不附加到它。
我使用此命令的变体来运行启动时不守护进程的“守护进程”(如 Minecraft),效果很好。我可以screen
稍后连接到会话并查看完整输出并像平常一样发出服务器命令。下面是启动脚本变体,它以非 root 用户身份运行屏幕会话(对于 /etc/rc.local):
sudo -u <someuser> -i screen -d -m <command>