如何在服务器上记录所有用户的Bash命令日志?

我们的小公司运行一个Ubuntu Server 11.10,有几个人有SSH访问权限。实际终端有时也会被使用。我们如何本地记录所有运行的Bash命令,以及用户和时间戳?
我们可以假设没有人是邪恶的并且积极试图避免记录,但我们仍然希望用户不能直接写入其日志文件。必须正确处理同时会话。
6个回答

对于BASH shell,编辑系统范围的BASH运行时配置文件:
sudo -e /etc/bash.bashrc

追加到该文件的末尾:
export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"'

设置一个新文件来记录"local6"的日志。
sudo -e /etc/rsyslog.d/bash.conf

而且内容...

local6.*    /var/log/commands.log

重新启动 rsyslog:

sudo service rsyslog restart

退出。登录。就这样!
但是我忘了日志轮转:
sudo -e /etc/logrotate.d/rsyslog

有一个要按相同方式轮转的日志文件列表...

/var/log/mail.warn
/var/log/mail.err
[...]
/var/log/message

所以在列表中添加新的bash命令日志文件:
/var/log/commands.log

保存。

1忘记了我在答案中添加的日志轮转。 - user8290
1这种方法可以行得通,但我可以想出一种绕过它的方法(可能使用csh、.bash_logout)。我会采用Sabacon的acct解决方案。以下是这些优秀的阅读资料:http://www.linuxjournal.com/article/6144 和 http://beginlinux.com/blog/2010/01/monitoring-user-activity-with-psacct-or-acct/ - user8290
2我相信用户可以通过简单地重置或取消设置PROMPT_COMMAND,或者执行到非bash shell来轻松地停用它。 - Stefan Lasiewski
local6是有什么特别之处吗?它指的是什么? - Benubird
1@Benubird 看起来有几个预设的设施级别,其中8个是local0-local7:http://en.wikipedia.org/wiki/Syslog。0表示紧急情况,7表示调试,而6则接近7,代表“正常操作消息”。 - munchybunch
旋转是什么意思? - yukashima huksay
我无法使用这种方法记录脚本中运行的命令。 - karmendra
1由于日志文件如果不删除会变得很大,"rotating" 意味着旋转日志文件并删除较旧的文件以保持日志较小... - Badr Elmers

一个进程记账系统可能在这方面有所帮助,特别是acct软件包,它提供了lastcomm和ac命令。
ac命令打印关于用户连接时间的统计信息,以小时为单位。这是用户连接到系统的时间,无论是通过SSH远程连接还是串行终端,或者在控制台上。 lastcomm命令显示有关先前执行的命令的信息。最近的条目显示在列表的顶部。还显示了每个进程使用的CPU时间总量。
一个可能有用的旧教程在这里:

http://www.linuxjournal.com/article/6144?page=0,1

在这个教程中可以找到其他的会计命令,比如last等等。

http://www.techrepublic.com/article/system-accounting-in-linux/1053377


1lastcomm命令记录器相当无用。它只记录被运行的可执行文件,而不记录任何参数、开关或路径。 - Phil_1984_
lastcomm记录了很多垃圾信息。我看到了无尽的"df, tail, head, sleep, who"命令列表,但没有人运行过。 - xtian

你可以使用snoopy
Snoopy日志记录器可能非常适合你的目的。它并不打算成为一个不可避免的日志记录解决方案,而是一种对自己的行动保持跟踪的勤奋管理员的有用工具。
声明:我是snoopy的维护者。

请在回答中提供安装和使用的说明。 - muru
1详细的安装说明可在 Snoopy 的 GitHub 页面上找到,这是目前主要的 Snoopy 资源:https://github.com/a2o/snoopy。我反对在其他地方提供安装说明,因为主要位置是经过设计维护的,而其他地方则没有。顺便说一下,Readme 已经更新,结构更加清晰。 - Bostjan Skufca Jese
1也许是这样。但是没有提供使用所需步骤的摘要,这只是一个链接回答,很可能会被删除。 - muru
我访问了你的链接,我猜想在Ubuntu上安装指南应该是sudo make installsudo reboot,而不是make installreboot,但是make enable命令呢?在Ubuntu中,这个命令需要加上sudo前缀吗? - karel
1嗯,我提供了一个可行的替代方案的指引。如果这不是这个网站的目的,那么它应该被删除,同时也删除我的帐户。 - Bostjan Skufca Jese
@karel:是的,允许对/etc/ld.so.preload进行写操作。必须具备root权限。 - Bostjan Skufca Jese
谢谢。我现在明白了安装步骤。如果有其他人对这个安装程序有一般性的问题,请阅读这个回答 - karel
@karel 如果你愿意,可以在contrib/ubuntu/README中提供详细的Ubuntu特定安装说明...我会很乐意合并它,并在主要的README.md文件中添加一个指向它的链接。 - Bostjan Skufca Jese
2@BostjanSkufca 不必生气。这只是Stack Exchange的一种做法,要求至少有合理自成体系的答案。如果你坚决反对添加步骤,那就随你的意愿。我会保留我的负评。可能会有人给它点赞。 - muru
不生气。我现在明白了(关于自给自足的回答)。 - Bostjan Skufca Jese

你还可以尝试安装acct。Acct会详细记录在你的Linux系统上所做的操作的审计轨迹。
sudo apt-get install acct

为了避免多个会话覆盖历史文件,您需要在Bash启动文件中添加"shopt -s histappend"。同时,请参考这个问题以解决相同的问题。

尝试这个(上面的解决方案在bash 4.3中并不能完全有效):
export HISTTIMEFORMAT="%Y-%m-%d %T "
export PROMPT_COMMAND='trap "" 1 2 15; history -a >(tee -a ~/.bash_history | while read line; do if [[ $line =~ ^#[0-9]*$ ]]; then continue; fi; logger -p user.info -t "bash[$$]" "($USER) $line"; done); trap 1 2 15;'

这样做既可以记录日志,又可以防止记录用于Bash历史文件的时间戳。需要设置陷阱,因为在多次按下Ctrl+C后,Bash会将信号发送给"子作业"。这将强制当前用户注销(例如,使用sudo登录)。