Logging of interactive user sessions to rsyslog

History file is a great source of information, either if you do not remember your past actions, or if you are not a single administrator of a system, and you need to figure out what has been performed on it in the past. Unfortunately, history is not a very reliable source of information – the file does not always get written, the contents tend to be without date, and many additional details are lacking. Therefore – logging interactive session commands to rsyslog is a very solid idea, which will allow for easier post-mortem or just understanding what has happened to a server. Moreover – when the data is channelled through rsyslog, it is easy to redirect it to an external server and keep access logs safe – also gaining a better security level.

I have followed-up on a blog article here, however, while this article is excellent, it is over-complex for my taste. ELK at the back and so on – so I wanted something easier to deploy, and more “local”. Therefore I have created this simple guide.

There are three “legs” to this task. Setting up rsyslog to receive the logs, setting up logrotate to prevent the system overflowing with log files, and setting up the shell’s default PROMPT_COMMAND to run a command to push the last history entry to the logs.


I am making use of “local7” logging facility, which is easy to use, and, in most common cases – it is not being used by anything else. Using rsyslog modular design, add a file /etc/rsyslog.d/interactive_sessions.conf with the following content:

local7.*    /var/log/interactive_shell.log

Afterwards, restart rsyslog by running systemctl restart rsyslog


To prevent the logs from filling up all the free space, we will define logrotate. Again, using logrotate modular structure, we need to add a file called /etc/logrotate.d/interactive_shell with the following content:

/var/log/interactive_shell.log {
    rotate 30

This will enforce rotation of the log file and keeping 30 compressed files depth.

Update bash prompt

Interactive login imports files kept in /etc/profile.d/ so we will add a file /etc/profile.d/interactive_shell.sh with the following content:

export PROMPT_COMMAND='RETRN_VAL=$?; logger -S 10000 -p local7.debug "\"user\": \"$(whoami)\", \"path\": \"$(pwd)\", \"shell_pid\": \"$$\", \"command\": \"$(history 1 | sed -r "s/^\\s*[0-9]+\\s*//" )\", \"status\": \"$RETRN_VAL\""; unset LAST_OUTPUT; '

This code will call ‘logger’ command directed at “local7” with the contents of the last history line, and some additional details, such as the current running path, the shell PID, the user, and the return value of the command. Note that it will log the same last line in ‘history’ if just pressing ‘enter’

Wrapping it all up

After restarting rsyslog, the next interactive session will start creating the interactive_shell.log file, and contents will be kept inside. The log can be redirected to external syslog servers, keeping interactive commands well logged outside of malicious user’s grip, and assisting in post-mortem of stability or security events on the system.

This article was directed at Redhat version 7 and 8 family, and was tested on both platforms. Adjusting to different Linux, and even Unix flavours should be either trivial or very simple.

Let me know in the comments if this helped you!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.