我想要实现的是每当我使用 Yakuake/Konsole 时都能自动记录我的终端会话并归档。
如果在课程开始时我这样做,那么就很容易实现:
script -f /home/$USER/bin/shell_logs/$(date +"%d-%b-%y_%H-%M-%S")_shell.log
但我想每当我启动 Yakuake 或打开新选项卡时自动运行上述内容。
使用 .bashrc 不起作用,因为它会创建无限循环,因为“脚本”打开一个新会话,该会话又读取 .bashrc 并启动另一个“脚本”,依此类推。
因此,大概我需要以某种方式编写 Yakuake/Konsole 脚本,以便在打开新选项卡时运行“脚本”一次。问题是如何?
答案1
如果有人想要使用该script
实用程序自动记录他们的终端会话(包括 SSH 会话(!)),请按以下方法操作。
.bashrc
在主目录的末尾添加以下行,或者/etc/bash.bashrc
如果您只想记录所有用户的会话,则添加以下行。我们测试 shell 的父进程是否不存在script
,然后运行script
。
对于Linux:
test "$(ps -ocommand= -p $PPID | awk '{print $1}')" == 'script' || (script -f $HOME/$(date +"%d-%b-%y_%H-%M-%S")_shell.log)
对于 BSD 和 macOS,更改script -f
为script -F
:
test "$(ps -ocommand= -p $PPID | awk '{print $1}')" == 'script' || (script -F $HOME/$(date +"%d-%b-%y_%H-%M-%S")_shell.log)
就这样!
现在,当您打开新终端时,您将看到:
Script started, file is /home/username/file_name.log
script
会将您的会话写入主目录中的文件中,并将其命名为类似于30-Nov-11_00-11-12_shell.log
结果的文件。
更多定制:
- 您可以将会话附加到一个大文件,而不是为每个会话创建一个新文件
script -a /path/to/single_log_file
script -f
您可以通过更改(Linux)或script -F
(BSD 和 macOS)后的路径来调整文件的写入位置
script
当然,这个答案假设您已经安装了。在基于 Debian 的发行版上,script
是软件包的一部分bsdutils
。
答案2
尽管这个问题是由想要记录自己的会话的个人提出的,但替代用例可能是想要跟踪各个用户正在做什么的系统管理员。
我担心当机器的用户不愿意记录他们的会话时,
script
在系统范围内运行可能不适合。bashrc
希望保持隐身状态的用户可以通过要求 sshd 打开不同的 shell(例如
zsh
)或运行bash --rcfile ___
以防止/etc/bash.bashrc
加载来绕过日志记录。
另一种方法
本指南来自 2008 年(已归档)使用一个不同的方法当用户使用 ssh 登录时强制script
运行,这需要用户使用公钥/私钥登录。
这是通过将脚本添加到用户.ssh/authorized_keys
文件中的键前面来完成的:
command="/usr/local/sbin/log-session" ssh-dss AAAAB3NzaC1kc3MAAAEBAMKr1HxJz.....
这log-session
(已归档) 脚本然后决定是否运行/usr/bin/script
来记录该用户的会话。
exec script -a -f -q -c "$SSH_ORIGINAL_COMMAND" $LOGFILE
为了防止用户删除添加的命令,管理员需要承担用户authorized_keys
文件的所有权。
chown root:root ~user/.ssh/authorized_keys
不幸的是,这意味着用户将无法自己添加任何额外的密钥,或者更重要的是,如果现有密钥被泄露,则无法撤销现有密钥,这远非理想。
注意事项
sshd 的默认配置通常允许用户通过 ssh 登录执行 SFTP。这为用户提供了一种编辑文件而不记录更改的方法。如果管理员不希望用户能够执行此操作,那么他应该启用 SFTP 的某些日志记录,或者禁用该服务。尽管如此,用户仍然可以通过在终端中运行类似的命令来对文件进行看不见的更改:
curl "http://users.own.server/server/new_data" > existing_file
通过使用记录所有文件历史记录的写时复制文件系统,可以监视类似的更改。
但类似的技巧将允许用户在不记录命令的情况下执行命令:
curl "http://users.own.server/server/secret_commands_824" | sh
我不知道有什么简单的解决方案。可能性可能是:
- 记录所有网络数据(然后解开它)。
- 记录所有系统调用。
这种事情可能审计。
但不管怎么说...
记录用户会话不太可能为管理员提供任何真正的安全性。默认情况下,用户只能操作自己的文件,而不能损害系统。如果恶意用户确实设法提升权限,那么他可以禁用日志记录并删除日志(除非管理员已将日志配置为以仅附加方式存储在单独的计算机上)。
自动记录用户会话的管理员可能应该通知用户正在执行此操作。在某些司法管辖区,这种形式的数据收集可能违反数据或隐私法。至少,让用户意识到这一点是对他们的尊重。
管理员更有可能对记录
sudo
用户会话感兴趣。也许可以通过不同的答案或不同的问题来解决这个问题。
答案3
代替:
test "$(ps -ocommand= -p $PPID | awk '{print $1}')" == 'script' ||
我会用:
grep -qx "$PPID" <(pgrep -x "script") ||
在这种情况下双引号不是必需的,但我倾向于使用它们作为标准做法。我绝对建议在 grep 和 pgrep 中使用“x”开关,以避免与子字符串的罕见但有问题的匹配。