Rsyslog send a message programmatically - linux

How to send a message to rsyslog deamon programmatically (from a custom program)?
In the syslog there are openlog...syslog...closelog functions available. But how can i do it in case of rsyslog?

rsyslog is a central log program.
You could cat /etc/rsyslog.conf to watch how your rsyslog is configured.
Default configuration use imuxsock and imjournal.
imuxsock module actually listen like /dev/log or /run/systemd/journal/syslog. This means you could use syslog(3) man 3 syslog or cmd logger 123 to write log into /var/log/messages.
imjournal means rsyslog read log from systemd-journald(/var/log/journal/$(uuid)/*.journal. You could use sd-journal(3) api or journal cmd like echo 123 | systemd-cat to write to journal, and then rsyslog read log from it. you can see journal with journalctl -e to see the newest journal.

Related

stdout and stderr is not visible in syslog

We have a node.js application running as a daemon on a Linux (Yocto) gateway, but I see no trace from the application in the /var/log/syslog file. What would I have to do to include all console.log (stdout) messages into the syslog file?
I suspect this is not a development question and would be better on Superuser or other site.
But anyway.
You can pipe the output of the program through a program called logger which will copy all of its input into the log socket.
Or you could use a version of Linux that uses systemd and journald. The systemd log system will copy all stdout and stderr into its journal log.
Or you can use your own log file (not /var/log/syslog) and redirect the daemon's output into that file.

How to redirect output of systemd service to a file

I am trying to redirect output of a systemd service to a file but it doesn't seem to work:
[Unit]
Description=customprocess
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server
StandardOutput=/var/log1.log
StandardError=/var/log2.log
Restart=always
[Install]
WantedBy=multi-user.target
Please correct my approach.
I think there's a more elegant way to solve the problem: send the stdout/stderr to syslog with an identifier and instruct your syslog manager to split its output by program name.
Use the following properties in your systemd service unit file:
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote
Then, assuming your distribution is using rsyslog to manage syslogs, create a file in /etc/rsyslog.d/<new_file>.conf with the following content:
if $programname == '<your program identifier>' then /path/to/log/file.log
& stop
Now make the log file writable by syslog:
# ls -alth /var/log/syslog
-rw-r----- 1 syslog adm 439K Mar 5 19:35 /var/log/syslog
# chown syslog:adm /path/to/log/file.log
Restart rsyslog (sudo systemctl restart rsyslog) and enjoy! Your program stdout/stderr will still be available through journalctl (sudo journalctl -u <your program identifier>) but they will also be available in your file of choice.
Source via archive.org
If you have a newer distro with a newer systemd (systemd version 236 or newer), you can set the values of StandardOutput or StandardError to file:YOUR_ABSPATH_FILENAME.
Long story:
In newer versions of systemd there is a relatively new option (the github request is from 2016 ish and the enhancement is merged/closed 2017 ish) where you can set the values of StandardOutput or StandardError to file:YOUR_ABSPATH_FILENAME. The file:path option is documented in the most recent systemd.exec man page.
This new feature is relatively new and so is not available for older distros like centos-7 (or any centos before that).
I would suggest adding stdout and stderr file in systemd service file itself.
Referring : https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=
As you have configured it should not like:
StandardOutput=/home/user/log1.log
StandardError=/home/user/log2.log
It should be:
StandardOutput=file:/home/user/log1.log
StandardError=file:/home/user/log2.log
This works when you don't want to restart the service again and again.
This will create a new file and does not append to the existing file.
Use Instead:
StandardOutput=append:/home/user/log1.log
StandardError=append:/home/user/log2.log
NOTE: Make sure you create the directory already. I guess it does not support to create a directory.
You possibly get this error:
Failed to parse output specifier, ignoring: /var/log1.log
From the systemd.exec(5) man page:
StandardOutput=
Controls where file descriptor 1 (STDOUT) of the executed processes is connected to. Takes one of inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+console or socket.
The systemd.exec(5) man page explains other options related to logging. See also the systemd.service(5) and systemd.unit(5) man pages.
Or maybe you can try things like this (all on one line):
ExecStart=/bin/sh -c '/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server 2>&1 > /var/log.log'
If for a some reason can't use rsyslog, this will do:
ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"
Short answer:
StandardOutput=file:/var/log1.log
StandardError=file:/var/log2.log
If you don't want the files to be cleared every time the service is run, use append instead:
StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log
We are using Centos7, spring boot application with systemd. I was running java as below. and setting StandardOutput to file was not working for me.
ExecStart=/bin/java -jar xxx.jar -Xmx512-Xms32M
Below workaround solution working without setting StandardOutput. running java through sh as below.
ExecStart=/bin/sh -c 'exec /bin/java -jar xxx.jar -Xmx512M -Xms32M >> /data/logs/xxx.log 2>&1'
Assume logs are already put to stdout/stderr, and have systemd unit's log in /var/log/syslog
journalctl -u unitxxx.service
Jun 30 13:51:46 host unitxxx[1437]: time="2018-06-30T11:51:46Z" level=info msg="127.0.0.1
Jun 30 15:02:15 host unitxxx[1437]: time="2018-06-30T13:02:15Z" level=info msg="127.0.0.1
Jun 30 15:33:02 host unitxxx[1437]: time="2018-06-30T13:33:02Z" level=info msg="127.0.0.1
Jun 30 15:56:31 host unitxxx[1437]: time="2018-06-30T13:56:31Z" level=info msg="127.0.0.1
Config rsyslog (System Logging Service)
# Create directory for log file
mkdir /var/log/unitxxx
# Then add config file /etc/rsyslog.d/unitxxx.conf
if $programname == 'unitxxx' then /var/log/unitxxx/unitxxx.log
& stop
Restart rsyslog
systemctl restart rsyslog.service
In my case 2>&1(stdout and stderr file descriptor symbol) had to be placed correctly,then log redirection worked as I expected
[Unit]
Description=events-server
[Service]
User=manjunath
Type=simple
ExecStart=/bin/bash -c '/opt/events-server/bin/start.sh my-conf 2>&1 >> /var/log/events-server/events.log'
[Install]
WantedBy=multi-user.target
Make your service file call a shell script instead of running the app directly. This way you have extra control. For example, you can make output files like those in /var/log/
Make a shell script like /opt/myapp/myapp.sh
#!/bin/sh
/usr/sbin/logrotate --force /opt/myapp/myapp.conf --state /opt/myapp/state.tmp
logger "[myapp] Run" # send a marker to syslog
myapp > /opt/myapp/myapp.log 2>&1 &
And your service file myapp.service contains:
...
[Service]
Type=forking
ExecStart=/bin/sh -c /opt/myapp/myapp.sh
...
A sample of log config file /opt/myapp/myapp.conf
/opt/myapp/myapp.log {
daily
rotate 20
missingok
compress
}
Then you will get myapp.log, and zipped myapp.log.1.gz ... for each time the service was started, and previous zipped.

What happens to the new syslog messages when rsyslogd daemon is stopped?

I tried to search this in many places and also documents/man pages of openlog(), syslog(0, rsyslogd(8) but couldn't find answer for this.
My question is, if rsyslogd is stopped or not yet started, then do the new syslog messages get lost? Or rsyslogd fetches them from /dev/log later when it's enabled?
My test is:
On a running system, rsyslog is running. Now, do the following:
logger -p local7.notice "my custom message1"
grep message1 | /var/log/messages ----> Success
Stop rsyslogd process
logger -p local7.notice "My other custom message2"
now, start the rsyslogd daemon
grep message2 | /var/log/messages ----> FAIL
I understand from openlog(3) and syslog(3) man pages that a socket is opened for /dev/log file and if there is an error while sending the message to syslog (as rsyslogd is not running) then the connection is closed (and message is printed on console/stderror if you have used LOG_CONS/LOG_PERROR).
Could anybody please tell me:
Is there any way rsyslogd to get all those messages came in absence of it in syslog file when it comes up?
If not by default, is there any syscall, command,etc.etc.way to do that??
Thank you in advance.
-Neo
It won't happen by default. You can use the 'cat' command and pipe it to logger to get them in, though. Something like the following should work.
cat your.log | logger -n yourserver
You can also use the 'tail' command similarly to 'cat'.

How to stop Rsys from sending log data

Hello i am relatively new to rsyslog, and i have a file stored here /etc/rsyslog.d/ to tell rsyslog to send log data.
I now have enough data to analyze and would like to stop rsyslog from keep sending log data and waste my bandwidth.
So the question is how can i do this? Will removing the config file in /etc/rsyslog.d/ will simply stop rsyslog from sending the log file ?
Thanks.
Simply removing the file will not stop the logging.
you will have to issue a HUP to the PID of rsyslog.
kill -HUP <RSYSLOG PID>
This causes rsyslog to reread its configuration files in this case minus your config in /etc/rsyslog.d

Adding year in the syslog message (linux)

I need to log the year in the log message generated by syslog daemon. In particular in the /var/log/secure file. Is it possible?
Here an example of normal syslog message:
Feb 16 04:06:58 HOST sshd[28573]: Accepted password for USER from SOURCE port 7269 ssh2
And I need something similar to:
Feb 16 2011 04:06:58 HOST sshd[28573]: Accepted password for USER from SOURCE port 7269 ssh2
Thanks in advance.
If you use rsyslog, it is easy. Refer to following:
Modify /etc/rsyslog.conf to following:
...
authpriv.* /var/log/secure;RSYSLOG_FileFormat
...
And then asking rsyslog daemon to reload configuration:
$ kill -HUP <pid of rsyslog daemon>
More reference :
http://www.rsyslog.com/doc/rsyslog_recording_pri.html
http://www.rsyslog.com/doc/rsyslog_conf_modules.html/rsyslog_conf_templates.html
syslog-ng has the ts_format() option to specify the default timestamp format for files. it is set to iso format by default, which includes the year.
you can also configure file formats using the template() option.
If your syslog respects RFC 3164 (The BSD Syslog Protocol), then you cannot configure it to record the year. Unless you have a modern syslog daemon that follows RFC 5424 (rsyslog or syslog-ng) you cannot do that.
If you can't alter the syslog on the system itself, maybe you could setup syslog to send it to a remote system with a better syslog daemon?

Resources