diff --git a/实时 history 监控 b/实时 history 监控 index 3bec8f2..eea8d1f 100644 --- a/实时 history 监控 +++ b/实时 history 监控 @@ -1,7 +1,7 @@ #!/bin/bash -# 交互式实时命令监控脚本 - 稳定版 -# 版本: 4.2 +# 交互式实时命令监控脚本 - 清理安装版 +# 版本: 4.3 set -e @@ -23,6 +23,63 @@ CURRENT_LOG="" LATEST_LOG="" DAEMON_MODE=false +# 清理所有残留文件和进程 +cleanup_all() { + echo -e "${YELLOW}正在清理所有残留...${NC}" + + # 停止所有监控进程 + echo -e "${BLUE}停止监控进程...${NC}" + pkill -f "monitor_history_files" 2>/dev/null || true + pkill -f "command_monitor" 2>/dev/null || true + + # 删除PID文件 + rm -f "/tmp/command_monitor.pid" 2>/dev/null || true + rm -f "/tmp/last_size_"* 2>/dev/null || true + + # 删除缓存文件 + rm -f "/tmp/ip_geo_cache.txt" 2>/dev/null || true + + # 删除旧的自启动配置 + echo -e "${BLUE}清理自启动配置...${NC}" + rm -f /etc/profile.d/command_monitor_auto.sh 2>/dev/null || true + rm -f /etc/systemd/system/command-monitor.service 2>/dev/null || true + systemctl daemon-reload 2>/dev/null || true + + # 清理rc.local中的配置 + if [ -f "/etc/rc.local" ]; then + sed -i '/command_monitor.sh/d' "/etc/rc.local" 2>/dev/null || true + fi + if [ -f "/etc/rc.d/rc.local" ]; then + sed -i '/command_monitor.sh/d' "/etc/rc.d/rc.local" 2>/dev/null || true + fi + + # 清理日志文件(保留最新的3个) + echo -e "${BLUE}清理日志文件...${NC}" + if [ -d "$LOG_DIR" ]; then + # 保留最新的3个日志文件 + ls -t "$LOG_DIR"/*.log 2>/dev/null | tail -n +4 | xargs rm -f 2>/dev/null || true + echo -e "${GREEN}日志文件清理完成${NC}" + fi + + # 删除旧版本脚本 + rm -f "/usr/local/bin/command_monitor" 2>/dev/null || true + rm -f "/usr/bin/command_monitor" 2>/dev/null || true + + echo -e "${GREEN}✓ 所有残留已清理完成${NC}" +} + +# 检查磁盘空间 +check_disk_space() { + local available_space=$(df / | awk 'NR==2{print $4}') + if [ "$available_space" -lt 10240 ]; then # 小于10MB + echo -e "${RED}磁盘空间不足,可用空间: ${available_space}KB${NC}" + echo -e "${YELLOW}建议清理磁盘空间后再继续${NC}" + return 1 + fi + echo -e "${GREEN}磁盘空间充足: ${available_space}KB${NC}" + return 0 +} + # 获取时间戳 timestamp() { date '+%Y-%m-%d %H:%M:%S' @@ -195,65 +252,79 @@ monitor_history_files() { done } -# 安装脚本到系统 +# 安装脚本到系统(优化版) install_script() { echo -e "${GREEN}正在安装脚本到系统...${NC}" - # 创建简单的本地版本 + # 检查磁盘空间 + if ! check_disk_space; then + echo -e "${RED}磁盘空间不足,安装中止${NC}" + return 1 + fi + + # 先清理残留 + cleanup_all + + # 创建简化版脚本 cat > "$SCRIPT_PATH" << 'EOF' #!/bin/bash -# 命令监控脚本 - 本地安装版 +# 简化版命令监控脚本 LOG_DIR="/root/command_monitor_logs" PID_FILE="/tmp/command_monitor.pid" +LOG_FILE="$LOG_DIR/command_monitor.log" -start_monitor() { +start_daemon() { mkdir -p "$LOG_DIR" - nohup bash -c ' + + # 后台监控进程 + ( while true; do for user_dir in /home/* /root; do - if [ -d "$user_dir" ]; then - user=$(basename "$user_dir") - history_file="$user_dir/.bash_history" - if [ -f "$history_file" ]; then - current_size=$(stat -c%s "$history_file" 2>/dev/null || echo 0) - last_size=$(cat "/tmp/last_size_$user" 2>/dev/null || echo 0) - - if [ "$current_size" -gt "$last_size" ]; then - new_command=$(tail -n 1 "$history_file" 2>/dev/null) - if [ -n "$new_command" ] && [ "${#new_command}" -gt 2 ]; then - client_ip=$(who -m 2>/dev/null | awk "{print \$5}" | sed "s/[()]//g" | head -1) - echo "[$(date "+%Y-%m-%d %H:%M:%S")] 用户: $user | 命令: $new_command | 来源: $client_ip" >> "$LOG_DIR/monitor.log" - fi - echo "$current_size" > "/tmp/last_size_$user" - fi + [ -d "$user_dir" ] || continue + user=$(basename "$user_dir") + history_file="$user_dir/.bash_history" + [ -f "$history_file" ] || continue + + current_size=$(stat -c%s "$history_file" 2>/dev/null || echo 0) + last_size_file="/tmp/last_size_$user" + last_size=$(cat "$last_size_file" 2>/dev/null || echo 0) + + if [ "$current_size" -gt "$last_size" ]; then + new_command=$(tail -n 1 "$history_file" 2>/dev/null | sed 's/^[ \t]*//;s/[ \t]*$//') + if [ -n "$new_command" ] && [ ${#new_command} -gt 2 ] && [[ ! "$new_command" =~ ^(ls|cd|pwd|history|exit|clear)$ ]]; then + client_ip=$(who -m 2>/dev/null | awk '{print $5}' | sed 's/[()]//g' | head -1) + echo "[$(date "+%Y-%m-%d %H:%M:%S")] 用户: $user | 命令: $new_command | 来源: $client_ip" >> "$LOG_FILE" fi + echo "$current_size" > "$last_size_file" fi done sleep 1 done - ' > /dev/null 2>&1 & + ) & echo $! > "$PID_FILE" echo "监控已启动 (PID: $!)" } -stop_monitor() { +stop_daemon() { if [ -f "$PID_FILE" ]; then pid=$(cat "$PID_FILE") - kill "$pid" 2>/dev/null && echo "监控已停止" || echo "停止监控失败" + kill "$pid" 2>/dev/null && echo "监控已停止" || echo "停止失败" rm -f "$PID_FILE" + rm -f /tmp/last_size_* 2>/dev/null else echo "监控未运行" fi } case "$1" in - start) start_monitor ;; - stop) stop_monitor ;; - status) + start) start_daemon ;; + stop) stop_daemon ;; + status) if [ -f "$PID_FILE" ] && ps -p $(cat "$PID_FILE") >/dev/null 2>&1; then echo "监控运行中 (PID: $(cat "$PID_FILE"))" + [ -f "$LOG_FILE" ] && echo "最新日志:" && tail -1 "$LOG_FILE" 2>/dev/null || true else echo "监控未运行" fi @@ -277,23 +348,8 @@ setup_auto_start() { install_script fi - # 创建简单的rc.local启动(兼容性更好) - if [ -d "/etc/rc.d" ]; then - # 对于使用rc.local的系统 - local rclocal_file="/etc/rc.d/rc.local" - else - local rclocal_file="/etc/rc.local" - fi - - # 确保rc.local存在并可执行 - touch "$rclocal_file" - chmod +x "$rclocal_file" - - # 添加启动命令(如果不存在) - if ! grep -q "command_monitor.sh" "$rclocal_file"; then - echo "# 命令监控服务自启动" >> "$rclocal_file" - echo "nohup $SCRIPT_PATH start > /dev/null 2>&1 &" >> "$rclocal_file" - fi + # 使用crontab实现自启动(更可靠) + (crontab -l 2>/dev/null | grep -v "command_monitor.sh"; echo "@reboot $SCRIPT_PATH start > /dev/null 2>&1") | crontab - echo -e "${GREEN}✓ 已设置开机自启动${NC}" echo -e "${YELLOW}重启后会自动启动监控服务${NC}" @@ -301,23 +357,21 @@ setup_auto_start() { # 取消开机自启动 remove_auto_start() { - if [ -d "/etc/rc.d" ]; then - local rclocal_file="/etc/rc.d/rc.local" - else - local rclocal_file="/etc/rc.local" - fi - - # 移除启动命令 - sed -i '/command_monitor.sh/d' "$rclocal_file" 2>/dev/null || true - + crontab -l 2>/dev/null | grep -v "command_monitor.sh" | crontab - echo -e "${YELLOW}✓ 已取消开机自动启动${NC}" } -# 后台运行监控(简化稳定版) +# 后台运行监控 start_background_monitor() { echo -e "${GREEN}启动后台监控服务...${NC}" - # 检查是否已经在运行 + # 如果已安装系统脚本,使用系统脚本 + if [ -f "$SCRIPT_PATH" ]; then + $SCRIPT_PATH start + return $? + fi + + # 否则使用内置功能 if [ -f "/tmp/command_monitor.pid" ]; then local old_pid=$(cat "/tmp/command_monitor.pid" 2>/dev/null) if ps -p "$old_pid" >/dev/null 2>&1; then @@ -326,40 +380,30 @@ start_background_monitor() { fi fi - # 直接启动监控进程 ( - # 设置环境 DAEMON_MODE=true init_log_system configure_realtime_history - # 记录启动信息 log_message "INFO" "后台监控进程启动 - PID: $$" log_message "INFO" "客户端IP: $(get_client_ip)" log_message "INFO" "地理位置: $(get_ip_location $(get_client_ip))" - # 保存PID echo $$ > "/tmp/command_monitor.pid" - - # 启动监控主循环 monitor_history_files - ) & local main_pid=$! - - # 等待并检查启动状态 sleep 2 + if ps -p $main_pid >/dev/null 2>&1; then echo -e "${GREEN}✓ 后台监控已启动!${NC}" echo -e "主进程PID: $main_pid" echo -e "日志文件: $LATEST_LOG" echo -e "查看日志: ${GREEN}tail -f $LATEST_LOG${NC}" - echo -e "停止监控: ${RED}选择菜单选项4${NC}" return 0 else echo -e "${RED}✗ 后台监控启动失败${NC}" - echo -e "${YELLOW}建议使用前台模式或重新启动${NC}" return 1 fi } @@ -367,13 +411,11 @@ start_background_monitor() { # 前台运行监控 start_foreground_monitor() { echo -e "${YELLOW}前台运行模式 (输入 TO 切换后台,Ctrl+C 停止)${NC}" - echo -e "${GREEN}开始监控...${NC}" DAEMON_MODE=false init_log_system configure_realtime_history - # 显示启动信息 local client_ip=$(get_client_ip) local location_info=$(get_ip_location "$client_ip") @@ -381,35 +423,24 @@ start_foreground_monitor() { log_message "INFO" "客户端IP: $client_ip" log_message "INFO" "地理位置: $location_info" - echo -e "${BLUE}监控信息:${NC}" - echo -e " 客户端IP: $client_ip" - echo -e " 地理位置: $location_info" - echo -e " 日志文件: $CURRENT_LOG" - echo -e " 输入 ${CYAN}TO${NC} 切换到后台模式" - echo -e "${GREEN}等待命令输入...${NC}" + echo -e "${GREEN}开始监控...${NC}" + echo -e "客户端IP: $client_ip" + echo -e "地理位置: $location_info" + echo -e "输入 ${CYAN}TO${NC} 切换到后台模式" - # 启动监控进程 monitor_history_files & local monitor_pid=$! - # 等待用户输入TO切换 while true; do - # 使用短超时读取,避免阻塞 - if read -t 1 -r user_input; then + if read -t 1 user_input; then if [ "$user_input" = "TO" ] || [ "$user_input" = "to" ]; then echo -e "\n${GREEN}切换到后台模式...${NC}" kill $monitor_pid 2>/dev/null || true - if start_background_monitor; then - exit 0 - else - echo -e "${RED}切换到后台失败,保持前台模式${NC}" - monitor_history_files & - monitor_pid=$! - fi + start_background_monitor + exit 0 fi fi - # 检查监控进程是否还在运行 if ! ps -p $monitor_pid >/dev/null 2>&1; then echo -e "${RED}监控进程异常退出${NC}" break @@ -419,24 +450,18 @@ start_foreground_monitor() { # 查看监控状态 check_monitor_status() { - local pid_file="/tmp/command_monitor.pid" + # 优先使用系统脚本检查 + if [ -f "$SCRIPT_PATH" ]; then + $SCRIPT_PATH status + return $? + fi - if [ -f "$pid_file" ]; then - local main_pid=$(cat "$pid_file" 2>/dev/null) + if [ -f "/tmp/command_monitor.pid" ]; then + local main_pid=$(cat "/tmp/command_monitor.pid") if ps -p "$main_pid" >/dev/null 2>&1; then echo -e "${GREEN}✓ 监控服务运行中${NC}" echo "主进程PID: $main_pid" - echo "日志目录: $LOG_DIR" - - if [ -f "$LATEST_LOG" ]; then - local log_size=$(du -h "$LATEST_LOG" 2>/dev/null | cut -f1 || echo "未知") - echo "当前日志大小: $log_size" - echo - echo -e "${YELLOW}最近3条记录:${NC}" - tail -3 "$LATEST_LOG" 2>/dev/null | while read line; do - echo " $line" - done || echo " 无法读取日志" - fi + [ -f "$LATEST_LOG" ] && echo "最新日志:" && tail -1 "$LATEST_LOG" 2>/dev/null || true return 0 fi fi @@ -447,33 +472,21 @@ check_monitor_status() { # 停止监控进程 stop_monitor() { - local pid_file="/tmp/command_monitor.pid" + # 优先使用系统脚本停止 + if [ -f "$SCRIPT_PATH" ]; then + $SCRIPT_PATH stop + return $? + fi - if [ -f "$pid_file" ]; then - local main_pid=$(cat "$pid_file") + if [ -f "/tmp/command_monitor.pid" ]; then + local main_pid=$(cat "/tmp/command_monitor.pid") echo -e "${YELLOW}正在停止监控进程 (PID: $main_pid)...${NC}" kill "$main_pid" 2>/dev/null || true - sleep 2 - - if ps -p "$main_pid" >/dev/null 2>&1; then - echo -e "${RED}强制停止监控进程...${NC}" - kill -9 "$main_pid" 2>/dev/null || true - fi - - rm -f "$pid_file" + sleep 1 + rm -f "/tmp/command_monitor.pid" echo -e "${GREEN}✓ 监控进程已停止${NC}" else - # 尝试查找并停止任何监控进程 - local monitor_pids=$(pgrep -f "monitor_history_files" 2>/dev/null || true) - if [ -n "$monitor_pids" ]; then - echo -e "${YELLOW}发现监控进程,正在停止...${NC}" - kill $monitor_pids 2>/dev/null || true - sleep 1 - kill -9 $monitor_pids 2>/dev/null || true - echo -e "${GREEN}✓ 监控进程已停止${NC}" - else - echo -e "${YELLOW}没有找到运行的监控进程${NC}" - fi + pkill -f "monitor_history_files" 2>/dev/null && echo -e "${GREEN}✓ 监控进程已停止${NC}" || echo -e "${YELLOW}没有找到运行的监控进程${NC}" fi } @@ -481,7 +494,7 @@ stop_monitor() { show_interactive_menu() { clear echo -e "${GREEN}========================================${NC}" - echo -e "${GREEN} 实时命令监控系统 v4.2${NC}" + echo -e "${GREEN} 实时命令监控系统 v4.3${NC}" echo -e "${GREEN}========================================${NC}" echo echo -e "${YELLOW}请选择操作:${NC}" @@ -493,12 +506,13 @@ show_interactive_menu() { echo -e " ${CYAN}5${NC}. 设置开机自启动" echo -e " ${CYAN}6${NC}. 取消开机自启动" echo -e " ${CYAN}7${NC}. 安装脚本到系统" + echo -e " ${CYAN}8${NC}. 清理所有残留" echo -e " ${CYAN}0${NC}. 退出" echo echo -e "${GREEN}========================================${NC}" echo -e "${YELLOW}提示:${NC}" echo -e " - 前台模式下输入 ${CYAN}TO${NC} 可切换到后台" - echo -e " - 建议先安装脚本到系统 (选项7)" + echo -e " - 建议先选择8清理残留,再选择7安装" echo -e "${GREEN}========================================${NC}" echo } @@ -506,79 +520,40 @@ show_interactive_menu() { # 处理用户选择 handle_user_choice() { local choice - read -p "请输入选择 [0-7]: " choice + read -p "请输入选择 [0-8]: " choice case $choice in - 1) - start_background_monitor - ;; - 2) - start_foreground_monitor - ;; - 3) - check_monitor_status - ;; - 4) - stop_monitor - ;; - 5) - setup_auto_start - ;; - 6) - remove_auto_start - ;; - 7) - install_script - ;; - 0) - echo -e "${GREEN}再见!${NC}" - exit 0 - ;; - *) - echo -e "${RED}无效选择,请重新输入${NC}" - ;; + 1) start_background_monitor ;; + 2) start_foreground_monitor ;; + 3) check_monitor_status ;; + 4) stop_monitor ;; + 5) setup_auto_start ;; + 6) remove_auto_start ;; + 7) install_script ;; + 8) cleanup_all ;; + 0) echo -e "${GREEN}再见!${NC}"; exit 0 ;; + *) echo -e "${RED}无效选择,请重新输入${NC}" ;; esac echo read -p "按回车键返回菜单..." } -# 清理开机自启动配置 -cleanup_auto_start() { - # 移除有问题的自启动配置 - rm -f /etc/profile.d/command_monitor_auto.sh 2>/dev/null || true -} - ### 主程序 ### main() { local command="${1:-}" - # 清理旧的自启动配置 - cleanup_auto_start - case "$command" in - -d|--daemon) - start_background_monitor - ;; - -s|--status) - check_monitor_status - ;; - -k|--kill) - stop_monitor - ;; - -h|--help|"") - show_interactive_menu - handle_user_choice - ;; - *) - echo -e "${RED}未知选项: $command${NC}" - echo "使用: $0 [--daemon|--status|--kill|--help]" - exit 1 - ;; + -d|--daemon) start_background_monitor ;; + -s|--status) check_monitor_status ;; + -k|--kill) stop_monitor ;; + -c|--clean) cleanup_all ;; + -h|--help|"") show_interactive_menu; handle_user_choice ;; + *) echo -e "${RED}未知选项: $command${NC}"; exit 1 ;; esac } -# 直接运行显示菜单 +# 启动 if [ $# -eq 0 ]; then while true; do show_interactive_menu