Logging of commands executed in Bash

Sometime back, we had a requirement to log commands run on the terminal in the Bash shell. This was solved by means of a startup script with essentially the following contents:

#!/bin/bash

SESSION_LAST_COMMAND=

log_last_command() {
    local command

    command=$(history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//")

    if [[ -n "$SESSION_LAST_COMMAND" ]]; then
        logger -p local3.notice "shell user [$$]: Executed command: $command"
    fi

    SESSION_LAST_COMMAND="$command"
}

export PROMPT_COMMAND=log_last_command

It works fine except that pressing ENTER logs the last command again. This happens as many times as the enter key is pressed. And some users do have this habit! Is there a way to avoid these extra logs? Also, an obvious expectation from the solution will that a distinction between just pressing enter a few times and actually re-running the command be possible.


Solution 1:

I managed to solve the problem of repeated command logging triggered by the ENTER key by replacing the "history 1" invocation by "history -a >(tee -a $HISTFILE)". Subsequently, after the last command has been found and logged, "history -c; history -r" is run to remove all entries from the Bash's in-memory command list and regenerate the list from whatever has been saved in the history file. This is necessary to get only a single command the next time "history -a" is executed. Here is the solution:

session_log_command() {
    local status=$?
    local command
    local cwd

    cwd=$PWD

    command=$(history -a >(tee -a $HISTFILE))

    if [[ -n "$command" ]]; then
        logger -p local3.notice "shell user [$$]: Executing command [CWD=$cwd ; $status]: $command"
        history -c; history -r
    fi
}

export PROMPT_COMMAND=session_log_command