Я пытаюсь запустить программу как системный модуль. Первоначально он не был спроектирован как единое целое, и кажется, что он иногда отправляет сообщения об ошибках в stdout вместо stderr, в то же время префикс сообщения с Error
.
Вместо того, чтобы пытаться изменить программу и перестроить ее, я надеялся, что мог бы быть способ, чтобы systemd отслеживал вывод журнала для ключевого слова Error
и перезапускал службу в этом случае.
Есть ли способ достижения этого, будь то встроенный в systemd или каким-либо образом, оборачивая эту программу в конвейер?
В итоге я написал небольшой скрипт-обертку на 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()