Skip to content

Instantly share code, notes, and snippets.

@dayreiner
Last active January 14, 2024 23:40
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save dayreiner/cbe525defc5159c2ae36 to your computer and use it in GitHub Desktop.
Save dayreiner/cbe525defc5159c2ae36 to your computer and use it in GitHub Desktop.
Log all users zsh / bash commands via syslog without 3rd-party tools or auditd

Sending Bash and ZSH Commands to Syslog

Also posted here: http://18pct.com/sending-bash-and-zsh-commands-to-syslog/

Your bash/zsh history is great if its complete, but it doesn't capture commands across all users, sudo's, root commands etc. In particular with test environments, someone may perform a "one-off" procedure and then months later it needs to be repeated. It would be nice to be able to look up what the user did at the time, and searching through multiple, possibly truncated history files is a pain.

Tools like typescript are great if you're actively documenting, but not something you would use all the time in practice and capture more than just a history of your commands. There are third-party tools like rootsh and Snoopy that can accomplish this, but third-party tools can be overkill if all you want is a quick reference in a relatively controlled environment.

If you need an "official" record of all user actions, you should be using process accounting or better-yet auditd instead (which can be configured to record all user commands). This method is just a trivial way to get a searchable record of all user actions on a box for convenience -- not for security or auditing purposes.

Syslog Setup

Assuming your distribution uses rsyslog, in /etc/rsyslog.d create a file called commands.log with the following contents:

local6.*    /var/log/commands.log

This will log anything going to local6 in to a local file called commands.log. You can adjust this as you want, or send everything to a central syslog server or logstash instance.

Bash and ZSH Setup

This method takes advantage of the built-in PROMPT_COMMAND variable in bash and the precmd function in ZSH. Both of these are used to execute something with every command entered in the shell, making them perfect for capturing command input and piping it to syslog.

Global Bash Profile Setup

Add the following line to the bottom of the global /etc/bashrc file on your system:

# Log commands to syslog for future reference
export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"'

Alternately, you can just add this to the end of your .bashrc if you just want to do this for a single user for some reason.

Global ZSH Profile Setup

Add the following line to the bottom of the global /etc/zshrc file on your system:

# Log commands to syslog for future reference
precmd() { eval 'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history | tail -n1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"' }

Alternately, you can just add this to the end of your .zshrc if you just want to do this for a single user for some reason.

Log Format

From now on, whenever someone logs into the system using bash or zsh, you'll get a nice log in order of all the commands that were executed on the box and by whom:

Feb 16 16:12:44 myhost root: jim [16285]: sudo yum update [1]
Feb 16 16:16:32 myhost bob: bob [10033]: docker ps  [0]
Feb 16 16:16:36 myhost satin: satin [10033]: docker ps -a [0]
@spirit986
Copy link

the file in rsyslog.d should be commands.conf ?

Yes I can confirm myself it is commands.conf inside /etc/rsyslog.d

@XCM-jj
Copy link

XCM-jj commented Mar 31, 2021

how to log command run with sh(/use/bin/sh /bin/sh )?

@Stef-Lan
Copy link

I tried using this code although whenever a new shell is opened or an empty command is sent, it will log the latest command used. Is there a way to avoid this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment