0

I have an issue with Rsyslog's 'omprog' module when trying to get it to interact with my python (2.7) code. Rsyslog is supposed to send desired messages to python's stdin, yet it does not receive anything. I wonder if anyone else has had better success with this output module?

Rsyslog.conf

module(load="omprog")
template(name="sshmsg" type="string" string="%msg%")
if ($programname == "myprogram") then {
    action(type="omprog"
           binary="/usr/sshtrack.py"
           template="sshmsg")
}

If I replace the binary with a test shell script containing a line below, it works

test.sh

!#/bin/sh

cat /dev/stdin >> /var/log/ssh2.log

I also tried reading stdin in the shell script into a variable using

var="$(</dev/stdin)"

and

var="$(cat /dev/stdin)"

Neither of the above resulted var containing anything

Finally, when trying to read stdin from python script, I get nothing. Sometimes, it says resource unavailable (errno 11) error message.

sshtrack.py

#!/usr/bin/python
import sys

f = open("/var/log/ssh2.log", "a", 0)

while True:
    f.write("Starting\n")
    for line in sys.stdin:
        f.flush()
        msg = line.strip()
        if not msg:
            break
        f.write(msg)
        f.write("\n")
    f.close()

The issue seems similar to can not read correctly from STDIN except adding a non-block flag did nothing.

Minregx
  • 5
  • 2
  • 6

2 Answers2

1

I notice that your template sshmsg doesn't end with a newline. Try changing it to string="%msg%\n". Though it won't matter to rsyslog, Python will not be able to give you the data until it sees a newline.

Then it should work, but you probably not see any output from your python as it is buffered. Try adding an f.flush() after the last write in the loop, or opening the file unbuffered.

omprog will keep the pipe open, sending multiple lines until your program exits.

Note, not all shells might understand $() syntax.

meuh
  • 11,500
  • 2
  • 29
  • 45
  • Tried both flushing and opening the file using unbuffered option. Stdin still seems empty. See **sshtrack.py** for changes.I can see the line "starting" in the file, but nothing from Stdin. – Minregx Apr 30 '20 at 06:57
  • I just noticed your template `sshmsg` doesnt end with a newline. Try changing it to `string="%msg%\n"`. Though it wont matter to rsyslog, python will not be able to give you the data until it sees a newline. (Also, put the flush after the write("\n"), if you remove the no buffering option). – meuh Apr 30 '20 at 07:38
0

In case of your shell script you can use read to read into a variable.

#!/bin/bash

# This will read until \n
read log

echo $log

The python source code (tested with python 3.8.2) can be adjusted to:

#!/usr/bin/env python3

import sys

# Changed from unbuffered to buffered as unbuffered is only possible in binary mode Ref (1):
f = open("/var/log/ssh2.log", "a", 1)

while True:
    f.write("Starting\n")
    for line in sys.stdin:
        f.flush()
        msg = line.strip()
        if not msg:
            break
        f.write(msg)
        f.write("\n")
    f.close()

In case you want to have the output of you executed script (debugging) you can adjust the settings in Rsyslog.conf with the output option

module(load="omprog")
template(name="sshmsg" type="string" string="%msg%")
if ($programname == "myprogram") then {
    action(type="omprog"
           binary="/usr/sshtrack.py"
           output="/var/log/sshtrack.log"
           template="sshmsg")
}

Ref (1): https://stackoverflow.com/a/45263101/13108341

Thomas
  • 1
  • 1