求助开发Ruby on Rails终端命令带时间日志CSV存储应用
实现Ruby on Rails终端命令日志到CSV的方案
嘿,这个需求挺实用的!我刚好折腾过类似的功能,给你一步步拆解怎么实现:
核心思路
如果是要在Rails应用内部捕获并记录执行的终端命令(比如你的应用代码里调用system、反引号执行的命令),我们可以封装一个工具类,把命令执行、日志记录、CSV写入的逻辑打包在一起。如果是要捕获服务器上所有终端用户输入的系统命令,那得结合shell配置来做,我后面也会提这个场景。
方案一:Rails应用内命令执行日志(推荐)
1. 创建命令日志服务类
在app/services目录下新建command_logger.rb,这个类负责执行命令、记录日志并写入CSV:
# app/services/command_logger.rb class CommandLogger CSV_PATH = Rails.root.join('log', 'command_logs.csv').to_s def self.execute_and_log(command) start_time = Time.now.utc # 用UTC时间避免时区问题,也可以换成Time.now.localtime # 执行命令并捕获输出(包括错误输出) output = `#{command} 2>&1` exit_status = $?.exitstatus end_time = Time.now.utc # 写入CSV文件 write_to_csv(command, start_time, end_time, exit_status, output) # 返回执行结果给调用方 { output: output, success: exit_status.zero? } end private def self.write_to_csv(command, start_time, end_time, exit_status, output) # 首次写入时添加表头 file_exists = File.exist?(CSV_PATH) CSV.open(CSV_PATH, 'a', force_quotes: true) do |csv| csv << ['命令内容', '开始时间(UTC)', '结束时间(UTC)', '退出状态', '执行输出'] unless file_exists csv << [ command, start_time.strftime('%Y-%m-%d %H:%M:%S.%L'), # 精确到毫秒 end_time.strftime('%Y-%m-%d %H:%M:%S.%L'), exit_status, output.strip ] end end end
2. 使用方式
你可以在控制器、定时任务或者rails控制台里直接调用这个服务:
# 示例1:在rails控制台测试 CommandLogger.execute_and_log('pwd') CommandLogger.execute_and_log('cd /tmp && ls -la') # 示例2:在控制器里提供web接口 class CommandsController < ApplicationController def run # 注意:如果允许用户输入命令,一定要做权限校验和命令白名单,防止注入攻击! result = CommandLogger.execute_and_log(params[:command]) render json: result end end
3. 注意事项
- 权限问题:确保Rails进程有
log目录的写入权限,避免CSV写入失败。 - 命令安全:如果允许用户通过web界面输入命令,一定要做严格的参数校验和白名单限制,绝对不能直接执行用户输入的任意命令!
- 时区调整:上面用的是UTC时间,如果你需要本地时间,把
Time.now.utc换成Time.now.localtime即可。
方案二:捕获服务器所有终端用户的命令(系统级)
如果你的需求是记录服务器上所有用户通过终端输入的命令(比如ssh登录后执行的cd、pwd等),那需要修改shell的配置:
- 编辑全局bash配置文件
/etc/bash.bashrc(针对所有用户)或者用户个人的~/.bashrc:
# 在文件末尾添加以下内容,把命令日志追加到指定文件 PROMPT_COMMAND='RETRN_VAL=$?; echo "$(date +%Y-%m-%d\ %H:%M:%S.%L) | $(whoami) | $(history 1 | sed "s/^[ ]*[0-9]*[ ]*//") | exit:$RETRN_VAL" >> /var/log/user_commands.log'
- 之后你可以在Rails里写一个定时任务(比如用Whenever gem),定期把这个日志文件转换成CSV格式,或者直接在应用里读取解析。
不过这种方式是系统级的,和Rails应用本身耦合度低,适合监控服务器操作日志的场景。
测试验证
运行几个命令后,去log/command_logs.csv里看看,应该能看到类似这样的内容:
"命令内容","开始时间(UTC)","结束时间(UTC)","退出状态","执行输出" "pwd","2024-05-20 12:34:56.123","2024-05-20 12:34:56.125","0","/home/rails/myapp" "cd /tmp && ls -la","2024-05-20 12:35:01.456","2024-05-20 12:35:01.458","0","total 8 drwxrwxrwt 2 root root 4096 May 20 12:35 . drwxr-xr-x 20 root root 4096 May 19 08:00 .."
内容的提问来源于stack exchange,提问作者L00n3y
相关产品推荐
相关产品推荐

