我正在尝试将程序作为 systemd 单元运行。它最初并不是设计为 systemd 单元,而且它似乎有时会将错误发布到 stdout 而不是 stderr,同时在消息前面加上。我希望有一种方法可以让 systemd 监视关键字的日志输出并在这种情况下重新启动服务,Error
而不是尝试修改程序并重建它。Error
有没有办法实现这一点,无论它是 systemd 中原生的还是通过以某种方式将该程序包装在管道中?
答案1
我最终用 Python 编写了一个小包装脚本,用于监视输出,如果输出中出现错误行,则退出该进程。
#!/usr/bin/env python3
import subprocess
import atexit
import sys
ALL_PROCESSES = []
def exit_handler():
for process in ALL_PROCESSES:
process.kill()
def main():
global ALL_PROCESSES
process = subprocess.Popen(<what-to-execute>,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
ALL_PROCESSES.append(process)
while True:
nextline = process.stdout.readline()
if nextline == '' and process.poll() is not None:
break
if 'error' in nextline.lower():
sys.stderr.write('Error occured, stopping child: {}'.format(nextline))
exit_handler()
sys.exit(1)
sys.stdout.write(nextline)
sys.stdout.flush()
output = process.communicate()[0]
exitCode = process.returncode
if (exitCode == 0):
return output
else:
raise ProcessException(command, exitCode, output)
def execute(cmd):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
for stdout_line in iter(popen.stdout.readline, ""):
yield stdout_line
popen.stdout.close()
return_code = popen.wait()
if return_code:
raise subprocess.CalledProcessError(return_code, cmd)
atexit.register(exit_handler)
if __name__ == '__main__':
main()