JaredC
JaredC

Reputation: 5310

History of non-interactive shell commands

I've been looking for a way to log some more detailed information about the history of commands. My main purpose is to have a rough log of commands that were issued in order to build rough server timelines when debugging issues with our application. It is not for highly detailed auditing purposes. I came across this post which suggested an excellent way to modify PROMPT_COMMAND to augment the history log with additional information about each command. It suggests adding the following to the ~/.bashrc file:

export PROMPT_COMMAND='hpwd=$(history 1); hpwd="${hpwd# *[0-9]*  }"; if [[ ${hpwd%% *} == "cd" ]]; then cwd=$OLDPWD; else cwd=$PWD; fi; hpwd="${hpwd% ### *} ### $cwd"; history -s "$hpwd"'

This works awesome, except that it only happens when the PS1 prompt is issued. Is there a way to enhance this to work with non-interactive shells (I think that's the correct term)?

For example, I would like:

ssh host "ls | grep home"

To create an entry for ls | grep home on host as well, but since this isn't done through a PS1 prompt the linked solution falls short.

I have looked into auditd a little. This is a great utility, but the level of detail was way more than I need. I could have parsed the logs pretty easily, but pipes, redirects, loops become a nightmare to rebuild sanely into something pretty like what history already reports.

Upvotes: 4

Views: 1334

Answers (2)

Derrick Johnson
Derrick Johnson

Reputation: 385

Check out SSHLog -- this seems to do what you're looking for: https://github.com/sshlog/agent/

I'm a code contributor on this project.

It monitors SSH sessions and reports each session and all the commands they run. The exit code and command output is also available.

By default it will write to a log file, but it is configurable and has plug-ins for remote syslog, slack alerts, e-mail, etc.

Upvotes: 1

tripleee
tripleee

Reputation: 189628

A simple wrapper around ssh would seem like a straightforward way to achieve this.

shout () {
    local host
    host=$1
    shift
    ssh "$host" <<____HERE
        echo "$@" >>\$HOME/.shout-history
        bash -c "$@"
____HERE
}

Or if you want the wrapper to run locally,

shout () {
    local host
    host=$1
    shift
    echo "$@" >>$HOME/.shout-history
    ssh "$host" "$@"
}

I called this shout in opposition to ssh which ought to be, you know, quiet. See also this. Of course, if you are admin, you could simply move /usr/bin/ssh to someplace obscure and force your users to run a /usr/local/bin/ssh with contents similar to the above. It's easy enough to bypass by a knowledgeable user, but if you're really draconian, there are ways to make it harder.

If you are the admin of the remote host, you could force all users to run /usr/local/bin/shout as their shell, for example, and populate it with something more or less similar.

#!/bin/bash
echo "$@" >>/home/root/im.in.ur.sh.reading.ur.seekrit.cmds.lol
exec /bin/bash -c "$@"

Just make sure the transcript file is world writable but not world readable.

Upvotes: 1

Related Questions