Bash: History to Syslog

Bash Shell

For those who still ignore, Bash 4 is out for a few days! Bash is the most used shell on UNIX hosts. Bash has a built-in mechanism to save a log of all commands executed by the user (default in $HOME/.bash_history) but this file belongs to the user itself and can be altered or removed when the shell exits. This is not a safe way to audit users activity.

Here are two methods to send a copy of all commands executed by the users to a Syslog server. The first one will use the Bash “trap” feature. The second one is a patch to apply in the Bash source code.

Using a trap

Just add the following lines in your /etc/profile:

function log2syslog
   declare command
   command=$(fc -ln -0)
   logger -p local1.notice -t bash -i — $USER : $command
trap log2syslog DEBUG

/etc/profile is parsed and executed when Bash is started. The goal is to use the trap feature and call a function each time the user generates activity. The trap function (log2syslog) will extract the last command from the history and log it to Syslog using the logger command. Very easy to implement but this method:

  • spawns new process at each command logged (can have a negative effect when the server activity is high)
  • is not transparent to the user (regular users can’t edit /etc/profile but can read it!)

That’s why the second method will be preferred.

Using a patch

The method is to apply a patch on the Bash source tree and recompile the shell. It requires a environment with a compiler and the source code but this method will use less CPU and will be completely transparent!

An example of patch is available here. It takes five minutes to manually apply the patch to the Bash 4 source tree.

Here is an example of Syslog message:

Feb 27 19:30:51 honey bash: HISTORY: PID=21099 UID=1000 echo foo!

To conclude, don’t forget that, on a legal point of view, your users must be aware of the activity monitoring in place! Adapt your message-of-the-day file (/etc/motd) to remind that the activity is logged.


  1. putting it in the bash profile doesn’t capture the logs if they invoke another bash shell. even bashrc has funky results. Any way to do iologging for sudoreplay?

  2. sorry never mind the double dash should do the same trick, at least for command args. So using the “s would just be some sort of alternative way to solve that.

    By mistake I had a single dash on one of our test systems …. :-}

  3. well better put some ” around the log text string, something like this:

    logger -p local1.notice -t bash -i — “$USER : $command”

    otherwise you might run into trouble when logger is referencing the previous args:

    user types: df -k -i
    result: df usage table as expected
    then user types: ls
    result: logger: invalid option — k
    user thinks: what the hell is going on here

  4. Read this if you need a bash history syslog patch for CentOS (has to be bash 3.2, you won’t have good luck getting 4.1 working on CentOS, as it breaks some networking-scripts and there aren’t any good src rpms for it anyway–the Fedora src rpms don’t install because of an md5sum mismatch on a patch file)

    I spent a few hours trying to find the right patch (for src rpm CentOS 5, bash 3.2) and eventually found a fully working src rpm on this blog.

  5. Please note that the dash after bash -i is a double dash which prevents the errors in above post.
    Another note to pay attention is that it records up until the previous command, so example if you run 2 commands and you are tailing the logs, you would always see up until the 2nd last command. Forgot the reasons why but that’s what happens when you don’t use the patch or builtin syslog in bash4.

    Thanks for the info anyway

  6. Just wanted to note: Bash 4.1 RC1 has syslog support builting. Nothing special, it just logs every history line to syslog with PID and UID.

  7. Are you sure to correclty use two “–” in the following line:

    “logger -p local1.notice -t bash -i — $USER : $command”

    In bash, “–” means strop processing the arguments.

  8. Hi and thanks history to syslog function.

    I added the above function in /etc/profile file but when i enter some command , sometimes getting the fallowing error and sometimes not.

    for example when i enter the “df -h”,i getting the fallowing error and its not logged command to syslog.

    logger: invalid option — h

    Why i have the fallowing error,do you have idea ?

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.