#!/bin/bash # 用法示例:curl -fsSL "https://pan.shumengya.top/d/scripts/login_info.sh" | bash # --- 精心选择的颜色定义 --- NONE='\033[00m' BOLD='\033[1m' # 主题色 (可根据喜好调整) # 可以选择一个主色调,例如蓝色系或绿色系 # 这里我们尝试用青色作为标题,黄色作为关键信息,白色作为次要信息 TITLE_COLOR='\033[01;36m' # 亮青色 (Bold Cyan) INFO_COLOR='\033[01;33m' # 亮黄色 (Bold Yellow) VALUE_COLOR='\033[00;37m' # 白色 (White) LABEL_COLOR='\033[00;32m' # 绿色 (Green) - 用于标签 SUBTLE_COLOR='\033[01;30m' # 深灰色/亮黑色 (Bold Black / Dark Gray) - 用于分隔符或不重要信息 BLUE_COLOR='\033[01;34m' # 亮蓝色 (Bold Blue) ORANGE_COLOR='\033[01;33m' # 亮黄色 (在16色终端中常作为橙色) - 使用 INFO_COLOR 相同的代码 # --- 设备名称和欢迎 --- HOSTNAME_TEXT=$(hostname) # 如果不再需要显示hostname,可以注释掉或删除这行 # --- 系统概览 --- OS_INFO=$(lsb_release -ds 2>/dev/null || echo "N/A") KERNEL_VERSION=$(uname -sr 2>/dev/null || echo "N/A") BOOT_TIME=$(uptime -s 2>/dev/null || who -b | awk '{print $3, $4}') UPTIME=$(uptime -p 2>/dev/null | sed 's/up //') LOAD_AVG=$(uptime 2>/dev/null | awk -F'load average: ' '{print $2}') echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}" echo -e "${TITLE_COLOR}${BOLD}系统概览${NONE}" echo -e " ${LABEL_COLOR}系统名称:${NONE} ${VALUE_COLOR}$(uname -a)${NONE}" echo -e " ${LABEL_COLOR}操作系统:${NONE} ${VALUE_COLOR}$OS_INFO${NONE}" echo -e " ${LABEL_COLOR}内核版本:${NONE} ${VALUE_COLOR}$KERNEL_VERSION${NONE}" echo -e " ${LABEL_COLOR}启动时间:${NONE} ${VALUE_COLOR}$BOOT_TIME${NONE}" echo -e " ${LABEL_COLOR}运行时间:${NONE} ${VALUE_COLOR}$UPTIME${NONE}" echo -e " ${LABEL_COLOR}平均负载:${NONE} ${VALUE_COLOR}$LOAD_AVG${NONE}" echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}" # --- 硬件资源 --- # 获取 CPU 型号,处理可能的多行输出,只取第一行,并去除首尾空格 CPU_MODEL=$(grep "model name" /proc/cpuinfo | head -n 1 | awk -F ':' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' || echo "N/A") CPU_CORES=$(grep -c "processor" /proc/cpuinfo 2>/dev/null || echo "N/A") # CPU 温度 (尽可能兼容更多机型) CPU_TEMP="" # 定义获取CPU温度的函数 get_cpu_temp() { local temp_c="" # 1. 尝试使用 sensors 命令 (如果安装了 lm-sensors) if command -v sensors &> /dev/null; then # 尝试匹配常见的CPU温度标签 # Package id 0: Intel/AMD 多核封装温度 # Tctl/Tdie: AMD Ryzen # Core 0: Intel Core # cpu_thermal: 树莓派/通用 # Composite: 部分嵌入式设备 temp_c=$(sensors | grep -iE '^(package id 0|tctl|tdie|core 0|cpu_thermal|composite|temp1):' | head -n 1 | awk '{print $2}' | tr -d '+°C') if [ -n "$temp_c" ]; then echo "$temp_c" return fi fi # 2. 尝试读取 /sys/class/thermal/thermal_zone* # 优先查找 x86_pkg_temp (Intel) 或 k10temp (AMD) 或 cpu-thermal (ARM) 或 acpitz for zone in /sys/class/thermal/thermal_zone*; do [ -e "$zone/type" ] || continue type=$(cat "$zone/type") if [[ "$type" == "x86_pkg_temp" || "$type" == "k10temp" || "$type" == "cpu-thermal" || "$type" == "acpitz" ]]; then if [ -r "$zone/temp" ]; then temp_raw=$(cat "$zone/temp") # 转换为摄氏度 (除以1000) if [ "$temp_raw" -gt 0 ] 2>/dev/null; then awk "BEGIN {printf \"%.1f\", $temp_raw/1000}" return fi fi fi done # 3. 如果还没找到,尝试任何 thermal_zone0 (通常是主要的) if [ -r "/sys/class/thermal/thermal_zone0/temp" ]; then temp_raw=$(cat "/sys/class/thermal/thermal_zone0/temp") if [ "$temp_raw" -gt 0 ] 2>/dev/null; then awk "BEGIN {printf \"%.1f\", $temp_raw/1000}" return fi fi } CPU_TEMP_VAL=$(get_cpu_temp) if [ -n "$CPU_TEMP_VAL" ]; then CPU_TEMP="(${INFO_COLOR}${CPU_TEMP_VAL}°C${VALUE_COLOR})" fi # 智能内存显示:小于 1GB 显示 MB,否则显示 GB (保留1位小数) MEM_TOTAL_MB=$(free -m | awk 'NR==2{print $2}') if [ "$MEM_TOTAL_MB" -ge 1000 ]; then MEM_TOTAL_DISPLAY=$(awk -v val="$MEM_TOTAL_MB" 'BEGIN {printf "%.1fGB", val/1024}') else MEM_TOTAL_DISPLAY="${MEM_TOTAL_MB}MB" fi MEM_USED_PERCENT=$(free -m | awk 'NR==2{printf "%.1f%%", $3*100/$2 }') MEM_AVAILABLE_MB=$(free -m | awk 'NR==2{print $7"MB"}') # 'available' 通常比 'free' 更能代表实际可用内存 # --- GPU 检测 --- # 优先使用 lspci 检测 VGA, 3D, Display 控制器 GPU_INFO="" if command -v lspci &> /dev/null; then # 获取设备列表,去除前面的地址信息,只保留设备名称 # 典型 lspci 输出: "00:02.0 VGA compatible controller: Intel Corporation ..." # 我们需要截取 "Intel Corporation ..." # 使用 sed 处理:匹配开头到第二个冒号之前的所有内容并删除 GPU_INFO=$(lspci | grep -iE 'vga|3d|display' | sed 's/^.*: .*[:] //') fi echo -e "${TITLE_COLOR}${BOLD}硬件资源${NONE}" echo -e " ${LABEL_COLOR}中央处理器 (CPU):${NONE}" echo -e " ${VALUE_COLOR}$CPU_MODEL - ${CPU_CORES} 核心 ${CPU_TEMP}${NONE}" if [ -n "$GPU_INFO" ]; then echo -e " ${LABEL_COLOR}图形处理器 (GPU):${NONE}" # 处理多显卡情况,逐行显示 echo "$GPU_INFO" | while read -r line; do echo -e " ${VALUE_COLOR}$line${NONE}" done fi echo -e " ${LABEL_COLOR}内存 (RAM):${NONE}" echo -e " ${VALUE_COLOR}总计: ${INFO_COLOR}$MEM_TOTAL_DISPLAY${VALUE_COLOR} | 已用: ${INFO_COLOR}$MEM_USED_PERCENT${VALUE_COLOR} | 可用: ${INFO_COLOR}$MEM_AVAILABLE_MB${NONE}" echo -e " ${LABEL_COLOR}存储空间:${NONE}" # --- 修改的存储部分 (删除进度条, 修改颜色) --- # 使用 df -hT 获取信息,-x 排除不必要的类型 (保留 overlay) # 使用 awk 跳过头部 (NR>1),并按列提取 (Filesystem, Type, Size, Used, Use%, Mounted on) # 注意:已添加 -x overlay 以隐藏 Docker 挂载卷 df -hT -x tmpfs -x devtmpfs -x devpts -x proc -x sysfs -x cgroup -x fusectl -x securityfs -x pstore -x efivarfs -x autofs -x overlay 2>/dev/null | awk 'NR>1 {print $1, $2, $3, $4, $6, $7}' | while read -r DEVICE TYPE SIZE USED PERCENT MOUNTPOINT; do # --- 已删除进度条的计算和绘制 --- echo -e " ${INFO_COLOR}${MOUNTPOINT}${NONE} (${VALUE_COLOR}${DEVICE} - ${TYPE}${NONE})" # --- 核心改动:将 总 和 已用 后面的数值改为蓝色 --- # LABEL_COLOR 用于标签文字 "总:" 和 "已用:" # BLUE_COLOR 用于数值 SIZE 和 USED # VALUE_COLOR 用于百分比 PERCENT 以及括号和逗号 echo -e " ${LABEL_COLOR}总:${NONE} ${BLUE_COLOR}${SIZE}${NONE}, ${LABEL_COLOR}已用:${NONE} ${BLUE_COLOR}${USED}${NONE} (${VALUE_COLOR}${PERCENT}${NONE})" done echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}" # --- 网络连接 --- echo -e "${TITLE_COLOR}${BOLD}网络连接${NONE}" INTERFACES_UP=$(ip -o link show up | awk -F': ' '{print $2}' | cut -d '@' -f 1) # 使用 cut 移除 @ifname 后缀 HAS_IP=false if [ -n "$INTERFACES_UP" ]; then for IFACE in $INTERFACES_UP; do if [[ "$IFACE" == "lo" ]]; then continue; fi # 跳过 lo 接口 # 跳过 Docker 相关接口 if [[ "$IFACE" == docker* || "$IFACE" == veth* || "$IFACE" == br-* ]]; then continue; fi IP_ADDRS=$(ip -4 addr show dev "$IFACE" 2>/dev/null | grep -oP 'inet \K[\d.]+' | tr '\n' ' ') IP_ADDRS_V6=$(ip -6 addr show dev "$IFACE" 2>/dev/null | grep -oP 'inet6 \K[0-9a-fA-F:]+' | grep -ivE '^fe80::' | head -n1 | tr '\n' ' ') # 只显示一个全局 IPv6 MAC_ADDR=$(ip link show dev "$IFACE" 2>/dev/null | awk '/ether/ {print $2}') if [ -n "$IP_ADDRS" ] || [ -n "$IP_ADDRS_V6" ]; then HAS_IP=true IFACE_TYPE_LABEL="" if [[ "$IFACE" == wlan* || "$IFACE" == wlp* || "$IFACE" == ath* || "$IFACE" == ra* ]]; then IFACE_TYPE_LABEL="(${LABEL_COLOR}WiFi${NONE}) " elif [[ "$IFACE" == eth* || "$IFACE" == enp* || "$IFACE" == eno* ]]; then IFACE_TYPE_LABEL="(${LABEL_COLOR}有线${NONE}) " # 添加对虚拟接口类型的更全面判断 elif [[ "$IFACE" == docker* || "$IFACE" == br-* || "$IFACE" == veth* || "$IFACE" == tun* || "$IFACE" == tap* || "$IFACE" == virbr* ]]; then IFACE_TYPE_LABEL="(${LABEL_COLOR}虚拟${NONE}) " # 考虑桥接接口 elif ip link show "$IFACE" | grep -q "bridge"; then IFACE_TYPE_LABEL="(${LABEL_COLOR}桥接${NONE}) " fi echo -e " ${INFO_COLOR}${BOLD}${IFACE}${NONE} ${IFACE_TYPE_LABEL}" [ -n "$IP_ADDRS" ] && echo -e " ${LABEL_COLOR}IPv4:${NONE} ${VALUE_COLOR}${IP_ADDRS% }${NONE}" # % 移除末尾空格 [ -n "$IP_ADDRS_V6" ] && echo -e " ${LABEL_COLOR}IPv6:${NONE} ${VALUE_COLOR}${IP_ADDRS_V6% }${NONE}" [ -n "$MAC_ADDR" ] && echo -e " ${LABEL_COLOR}MAC:${NONE} ${VALUE_COLOR}${MAC_ADDR}${NONE}" fi done fi if ! $HAS_IP; then echo -e " ${VALUE_COLOR}未检测到活动的网络连接或IP地址${NONE}" fi echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}" # --- Docker 容器 --- # 检查 docker 命令是否存在且守护进程正在运行 if command -v docker &> /dev/null && docker ps &> /dev/null; then DOCKER_RUNNING_COUNT=$(docker ps -q | wc -l) DOCKER_TOTAL_COUNT=$(docker ps -aq | wc -l) echo -e "${TITLE_COLOR}${BOLD}Docker 容器${NONE}" echo -e " ${LABEL_COLOR}容器数量:${NONE} ${VALUE_COLOR}运行中: ${INFO_COLOR}${DOCKER_RUNNING_COUNT}${VALUE_COLOR} / 总计: ${INFO_COLOR}${DOCKER_TOTAL_COUNT}${NONE}" if [ "$DOCKER_RUNNING_COUNT" -gt 0 ]; then # 获取名称列表,用逗号分隔 DOCKER_NAMES=$(docker ps --format "{{.Names}}" | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g') echo -e " ${LABEL_COLOR}运行列表:${NONE} ${VALUE_COLOR}${DOCKER_NAMES}${NONE}" fi echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}" fi # --- 活动与统计 --- LAST_LOGIN_INFO=$(last -n 1 -wFai 2>/dev/null | head -n 1) # -a 把hostname放最后, -i 显示IP LAST_LOGIN_DISPLAY="" if [[ "$LAST_LOGIN_INFO" == *"wtmp begins"* || -z "$LAST_LOGIN_INFO" || $(echo "$LAST_LOGIN_INFO" | wc -w) -lt 5 ]]; then # 增加字段数检查 LAST_LOGIN_DISPLAY="${VALUE_COLOR}无先前登录记录或记录格式异常${NONE}" else # --- 修改的上次登录部分 --- USER=$(echo "$LAST_LOGIN_INFO" | awk '{print $1}') # 对于 -wFai, IP/hostname 通常是第三列 FROM_IP_OR_HOST=$(echo "$LAST_LOGIN_INFO" | awk '{print $3}') # 精确提取日期和时间部分,跳过 'still' 和年份 (字段 4到7) LOGIN_TIME_FIELDS=$(echo "$LAST_LOGIN_INFO" | awk '{print $4, $5, $6, $7}') # 尝试用date格式化,如果失败则显示原始字段 LOGIN_TIME_FORMATTED=$(date -d "$LOGIN_TIME_FIELDS $(date +%Y)" +"%Y-%m-%d %H:%M:%S" 2>/dev/null) # 显式添加年份尝试格式化 if [ -z "$LOGIN_TIME_FORMATTED" ]; then LOGIN_TIME_FORMATTED="${VALUE_COLOR}${LOGIN_TIME_FIELDS}${NONE} (raw)" # 格式化失败,显示原始字段并标记 fi LAST_LOGIN_DISPLAY="${LABEL_COLOR}用户:${NONE} ${INFO_COLOR}$USER${NONE}, ${LABEL_COLOR}来自:${NONE} ${INFO_COLOR}$FROM_IP_OR_HOST${NONE}, ${LABEL_COLOR}时间:${NONE} ${VALUE_COLOR}$LOGIN_TIME_FORMATTED${NONE}" fi PACKAGE_COUNT=$(dpkg-query -f '${Package}\n' -W 2>/dev/null | wc -l || echo "N/A") # Debian/APT echo -e "${TITLE_COLOR}${BOLD}活动与统计${NONE}" echo -e " ${LABEL_COLOR}上次登录:${NONE} $LAST_LOGIN_DISPLAY" # 检查是否是 Debian/Ubuntu 系列系统,然后显示包数 if command -v dpkg-query &> /dev/null; then PACKAGE_COUNT=$(dpkg-query -f '${Package}\n' -W 2>/dev/null | wc -l || echo "N/A") echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}$PACKAGE_COUNT (Debian/APT)${NONE}" elif command -v rpm &> /dev/null; then PACKAGE_COUNT=$(rpm -qa 2>/dev/null | wc -l || echo "N/A") echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}$PACKAGE_COUNT (RPM/Yum/Dnf)${NONE}" elif command -v pacman &> /dev/null; then PACKAGE_COUNT=$(pacman -Qq 2>/dev/null | wc -l || echo "N/A") echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}$PACKAGE_COUNT (Pacman)${NONE}" else echo -e " ${LABEL_COLOR}软件包数:${NONE} ${VALUE_COLOR}N/A (未知包管理器)${NONE}" fi CURRENT_DATETIME=$(date +"%Y年%m月%d日 %A %H:%M:%S %Z") echo -e " ${LABEL_COLOR}当前登录时间:${NONE} ${VALUE_COLOR}$CURRENT_DATETIME$" echo -e "${SUBTLE_COLOR}───────────────────────────────────────────────────────────────────────────────${NONE}"