Update 实时 history 监控

This commit is contained in:
2025-10-22 00:16:26 +08:00
committed by GitHub
parent 3cdb025189
commit e1e4892310

View File

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