finger 是一个用于查询系统用户信息的传统Unix/Linux工具。它可以显示用户的登录名、真实姓名、终端、登录时间、空闲时间、办公室位置和电话号码等信息。虽然现代系统中较少使用,但它仍然在某些环境中有用。
在基于Debian/Ubuntu的系统上安装:
sudo apt-get update
sudo apt-get install finger
在基于RHEL/CentOS的系统上安装:
sudo yum install finger
# 或者
sudo dnf install finger
在基于Arch Linux的系统上安装:
sudo pacman -S finger
在macOS上,finger通常已预装,但可能被禁用。
finger [选项] [用户名...]
| 选项 | 说明 |
|---|---|
-s |
简短格式显示用户信息 |
-l |
长格式显示用户信息(默认) |
-p |
不显示.plan和.project文件内容 |
-m |
禁止用户名匹配(只匹配登录名) |
-h |
不显示.plan文件内容 |
-i |
空闲时间格式显示 |
-q |
快速模式,只显示登录名、终端和登录时间 |
-w |
窄格式输出,不显示全名 |
--help |
显示帮助信息 |
--version |
显示版本信息 |
# 显示所有登录用户
finger
# 简短格式显示
finger -s
# 快速模式
finger -q
输出示例:
Login Name Tty Idle Login Time Office Office Phone
john John Doe pts/0 1d Jan 15 09:30 Room 101 123-4567
jane Jane Smith pts/1 Jan 15 14:20 (192.168.1.100)
# 查询用户john的信息
finger john
# 查询多个用户
finger john jane
# 只匹配登录名
finger -m john
# 长格式显示用户信息
finger -l john
# 不显示.plan文件内容
finger -l -p john
长格式输出示例:
Login: john Name: John Doe
Directory: /home/john Shell: /bin/bash
Office: Room 101, 123-4567 Home Phone: 987-6543
Last login Tue Jan 15 14:30 (EST) on pts/0
No mail.
No Plan.
# 以空闲时间格式显示
finger -i
# 显示特定用户的空闲时间
finger -i john
finger命令从以下文件中获取用户信息:
包含用户的基本信息:
# 查看/etc/passwd中的用户信息
grep john /etc/passwd
# 输出: john:x:1001:1001:John Doe,Room 101,123-4567,987-6543:/home/john:/bin/bash
GECOS字段(第5个字段)包含finger显示的信息:
finger会检查用户家目录中的以下文件:
| 文件 | 用途 | 示例内容 |
|---|---|---|
~/.plan |
用户计划/状态信息 | Working on project X\nAvailable for meetings |
~/.project |
用户项目信息 | Web Application Development |
~/.forward |
邮件转发地址 | john@example.com |
# 为用户john创建.plan文件
echo "Working on the new website project.
Available for meetings 2-4 PM.
Currently reading: The Linux Command Line" > /home/john/.plan
# 创建.project文件
echo "Website Redesign Project
Deadline: 2024-12-31
Status: In progress" > /home/john/.project
# 设置文件权限
chown john:john /home/john/.plan /home/john/.project
chmod 644 /home/john/.plan /home/john/.project
现在使用finger查看:
finger john
输出示例:
Login: john Name: John Doe
Directory: /home/john Shell: /bin/bash
Office: Room 101, 123-4567 Home Phone: 987-6543
Last login Tue Jan 15 14:30 (EST) on pts/0
No mail.
Plan:
Working on the new website project.
Available for meetings 2-4 PM.
Currently reading: The Linux Command Line
Project:
Website Redesign Project
Deadline: 2024-12-31
Status: In progress
#!/bin/bash
# monitor_users.sh - 监控系统用户
LOG_FILE="/var/log/user_monitor.log"
THRESHOLD_HOURS=24 # 空闲时间阈值
echo "用户监控报告 - $(date)" | tee -a "$LOG_FILE"
echo "=========================================" | tee -a "$LOG_FILE"
# 获取所有登录用户
finger -s | tail -n +2 | while read line; do
if [ -n "$line" ]; then
# 解析finger输出
login=$(echo "$line" | awk '{print $1}')
name=$(echo "$line" | awk '{print $2}')
tty=$(echo "$line" | awk '{print $3}')
idle=$(echo "$line" | awk '{print $4}')
login_time=$(echo "$line" | awk '{print $5" "$6" "$7}')
echo "用户: $login ($name)" | tee -a "$LOG_FILE"
echo "终端: $tty" | tee -a "$LOG_FILE"
echo "登录时间: $login_time" | tee -a "$LOG_FILE"
echo "空闲时间: $idle" | tee -a "$LOG_FILE"
# 检查空闲时间是否过长
if [[ "$idle" == *"d"* ]]; then
days=$(echo "$idle" | sed 's/d//')
if [ "$days" -ge 1 ]; then
echo "警告: 用户 $login 已空闲 $days 天" | tee -a "$LOG_FILE"
fi
fi
echo "---" | tee -a "$LOG_FILE"
fi
done
echo "监控完成" | tee -a "$LOG_FILE"
#!/bin/bash
# employee_directory.sh - 员工信息查询系统
echo "=== 员工信息查询系统 ==="
echo "1. 查看所有员工"
echo "2. 搜索员工"
echo "3. 查看部门"
echo "4. 退出"
echo ""
read -p "请选择选项 (1-4): " choice
case $choice in
1)
echo ""
echo "所有员工列表:"
echo "=================="
# 从/etc/passwd获取所有普通用户
getent passwd | awk -F: '$3 >= 1000 && $3 < 60000 {print $1}' | while read user; do
finger -s "$user" 2>/dev/null | tail -n +2
done
;;
2)
read -p "输入员工用户名或姓名: " search_term
echo ""
echo "搜索结果:"
echo "=========="
# 搜索用户
getent passwd | grep -i "$search_term" | cut -d: -f1 | while read user; do
finger -l "$user" 2>/dev/null
echo "---"
done
;;
3)
echo ""
echo "部门列表:"
echo "1. 技术部"
echo "2. 市场部"
echo "3. 财务部"
read -p "选择部门: " dept
case $dept in
1) dept_users="john bob alice" ;;
2) dept_users="jane mary" ;;
3) dept_users="david susan" ;;
*) echo "无效选择"; exit 1 ;;
esac
echo ""
echo "部门成员:"
for user in $dept_users; do
finger -s "$user" 2>/dev/null | tail -n +2
done
;;
4)
echo "再见!"
exit 0
;;
*)
echo "无效选择"
exit 1
;;
esac
#!/bin/bash
# user_activity_report.sh - 用户活动报告
REPORT_FILE="/tmp/user_activity_$(date +%Y%m%d).txt"
echo "用户活动报告 - $(date)" > "$REPORT_FILE"
echo "======================================" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
# 1. 当前登录用户
echo "1. 当前登录用户:" >> "$REPORT_FILE"
echo "----------------" >> "$REPORT_FILE"
finger -s >> "$REPORT_FILE" 2>/dev/null
echo "" >> "$REPORT_FILE"
# 2. 近期登录用户
echo "2. 近期登录用户 (最近7天):" >> "$REPORT_FILE"
echo "-------------------------" >> "$REPORT_FILE"
last -7 >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
# 3. 用户最后登录时间
echo "3. 用户最后登录时间:" >> "$REPORT_FILE"
echo "------------------" >> "$REPORT_FILE"
lastlog >> "$REPORT_FILE" 2>/dev/null
echo "" >> "$REPORT_FILE"
# 4. 系统用户统计
echo "4. 系统用户统计:" >> "$REPORT_FILE"
echo "--------------" >> "$REPORT_FILE"
echo "总用户数: $(getent passwd | wc -l)" >> "$REPORT_FILE"
echo "普通用户数: $(getent passwd | awk -F: '$3 >= 1000 && $3 < 60000' | wc -l)" >> "$REPORT_FILE"
echo "系统用户数: $(getent passwd | awk -F: '$3 < 1000' | wc -l)" >> "$REPORT_FILE"
echo "当前登录用户数: $(who | wc -l)" >> "$REPORT_FILE"
echo "报告已生成: $REPORT_FILE"
# 查询远程主机上的用户(通常已禁用)
finger @example.com
finger user@example.com
# 指定端口(默认79)
finger user@example.com:79
传统finger服务使用79端口,由in.fingerd或fingerd守护进程提供。现代系统通常不安装或禁用此服务。
# 检查finger服务状态
netstat -tlnp | grep :79
systemctl status finger 2>/dev/null
# 安装finger服务(不推荐)
sudo apt-get install fingerd
# 通常不建议启用此服务
由于finger的安全问题和功能限制,现代系统使用以下替代方案:
# 显示登录用户信息
w
who
# 显示详细用户信息
w -i
who -a
# 显示用户最后登录时间
lastlog
# 显示登录历史
last
last -10 # 最近10次登录
# 显示用户身份信息
id
id john
# 显示用户所属组
id -Gn john
# 查询passwd数据库
getent passwd john
getent passwd | grep john
# 查询group数据库
getent group
# 查看用户登录日志
sudo grep "session opened" /var/log/auth.log
sudo lastb # 显示失败登录尝试
finger: command not found
解决方案:
# 安装finger包
sudo apt-get install finger
# 或
sudo yum install finger
# 验证安装
which finger
finger --version
# finger命令执行但无输出
解决方案:
# 检查用户是否存在
id john
grep john /etc/passwd
# 使用详细模式
finger -l john
# 检查用户家目录权限
ls -la /home/john/
# 确保.plan和.project文件可读
# finger不显示办公室、电话等信息
解决方案:
# 检查/etc/passwd中的GECOS字段
grep john /etc/passwd
# 应该包含逗号分隔的信息: John Doe,Room 101,123-4567,987-6543
# 使用chfn命令更新信息
sudo chfn -f "John Doe" -o "Room 101" -p "123-4567" -h "987-6543" john
# finger不显示.plan文件内容
解决方案:
# 检查.plan文件是否存在
ls -la /home/john/.plan
# 检查文件权限
chmod 644 /home/john/.plan
chown john:john /home/john/.plan
# 确保finger没有使用-p选项
finger john
# 而不是 finger -p john
| 命令 | 说明 |
|---|---|
w |
显示登录用户及其活动 |
who |
显示登录用户信息 |
last |
显示用户登录历史 |
lastlog |
显示所有用户最后登录时间 |
users |
显示登录用户名 |
id |
显示用户身份信息 |
chfn |
更改用户finger信息 |
getent |
从名称服务切换库获取条目 |
loginctl |
systemd登录管理器控制工具 |
pinky |
轻量级finger替代工具 |
pinky是finger的轻量级替代,功能类似但输出更简洁:
# 安装pinky
sudo apt-get install coreutils
# 使用pinky
pinky
pinky -l
pinky john
# pinky输出示例
Login Name TTY Idle When Where
john John Doe pts/0 1:30 Jan 15 09:30 :0
#!/bin/bash
# generate_employee_directory.sh - 生成员工通讯录
OUTPUT_FILE="/tmp/employee_directory_$(date +%Y%m%d).txt"
echo "员工通讯录 - $(date)" > "$OUTPUT_FILE"
echo "======================================" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# 获取所有普通用户
getent passwd | awk -F: '$3 >= 1000 && $3 < 60000 {print $1}' | while read user; do
echo "查询用户: $user" >&2
# 获取finger信息
finger_output=$(finger -l "$user" 2>/dev/null)
if [ -n "$finger_output" ]; then
# 解析信息
login=$(echo "$finger_output" | awk '/^Login:/ {print $2}')
name=$(echo "$finger_output" | awk '/^Name:/ {sub(/^Name:[ \t]*/, ""); print}')
directory=$(echo "$finger_output" | awk '/^Directory:/ {print $2}')
office=$(echo "$finger_output" | awk '/^Office:/ {sub(/^Office:[ \t]*/, ""); print}')
phone=$(echo "$finger_output" | awk '/^Home Phone:/ {sub(/^Home Phone:[ \t]*/, ""); print}')
last_login=$(echo "$finger_output" | awk '/^Last login/ {sub(/^Last login[ \t]*/, ""); print}')
# 输出到文件
echo "用户名: $login" >> "$OUTPUT_FILE"
echo "姓名: $name" >> "$OUTPUT_FILE"
echo "办公室: $office" >> "$OUTPUT_FILE"
echo "电话: $phone" >> "$OUTPUT_FILE"
echo "最后登录: $last_login" >> "$OUTPUT_FILE"
echo "---" >> "$OUTPUT_FILE"
fi
done
echo "通讯录已生成: $OUTPUT_FILE"
echo "总记录数: $(grep -c "用户名:" "$OUTPUT_FILE")"
#!/bin/bash
# user_login_monitor.sh - 用户登录状态监控
LOG_FILE="/var/log/user_login_monitor.log"
ALERT_THRESHOLD=3 # 同时登录的最大会话数
echo "$(date) - 开始用户登录监控" >> "$LOG_FILE"
# 获取所有登录用户
finger -s 2>/dev/null | tail -n +2 | awk '{print $1}' | sort | uniq -c | while read count user; do
echo "$(date) - 用户 $user 有 $count 个活跃会话" >> "$LOG_FILE"
# 检查是否超过阈值
if [ "$count" -gt "$ALERT_THRESHOLD" ]; then
echo "$(date) - 警告: 用户 $user 有 $count 个并发登录会话" >> "$LOG_FILE"
# 发送告警(示例:写入系统日志)
logger "用户登录告警: $user 有 $count 个并发会话"
# 获取详细信息
echo "$(date) - 详细会话信息:" >> "$LOG_FILE"
finger -s "$user" 2>/dev/null | tail -n +2 >> "$LOG_FILE"
fi
done
echo "$(date) - 用户登录监控完成" >> "$LOG_FILE"
#!/bin/bash
# system_users_report.sh - 系统用户信息报告
REPORT_FILE="/tmp/system_users_report_$(date +%Y%m%d).html"
echo "<!DOCTYPE html>" > "$REPORT_FILE"
echo "<html>" >> "$REPORT_FILE"
echo "<head>" >> "$REPORT_FILE"
echo " <meta charset=\"UTF-8\">" >> "$REPORT_FILE"
echo " <title>系统用户信息报告 - $(date)</title>" >> "$REPORT_FILE"
echo " <style>" >> "$REPORT_FILE"
echo " body { font-family: Arial, sans-serif; margin: 20px; }" >> "$REPORT_FILE"
echo " table { border-collapse: collapse; width: 100%; }" >> "$REPORT_FILE"
echo " th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }" >> "$REPORT_FILE"
echo " th { background-color: #f2f2f2; }" >> "$REPORT_FILE"
echo " tr:nth-child(even) { background-color: #f9f9f9; }" >> "$REPORT_FILE"
echo " </style>" >> "$REPORT_FILE"
echo "</head>" >> "$REPORT_FILE"
echo "<body>" >> "$REPORT_FILE"
echo " <h1>系统用户信息报告</h1>" >> "$REPORT_FILE"
echo " <p>生成时间: $(date)</p>" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
echo " <h2>当前登录用户</h2>" >> "$REPORT_FILE"
echo " <table>" >> "$REPORT_FILE"
echo " <tr><th>用户名</th><th>姓名</th><th>终端</th><th>空闲时间</th><th>登录时间</th></tr>" >> "$REPORT_FILE"
# 添加当前登录用户
finger -s 2>/dev/null | tail -n +2 | while read line; do
if [ -n "$line" ]; then
login=$(echo "$line" | awk '{print $1}')
name=$(echo "$line" | awk '{print $2}')
tty=$(echo "$line" | awk '{print $3}')
idle=$(echo "$line" | awk '{print $4}')
login_time=$(echo "$line" | awk '{print $5" "$6" "$7}')
echo " <tr><td>$login</td><td>$name</td><td>$tty</td><td>$idle</td><td>$login_time</td></tr>" >> "$REPORT_FILE"
fi
done
echo " </table>" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
echo " <h2>系统用户统计</h2>" >> "$REPORT_FILE"
echo " <ul>" >> "$REPORT_FILE"
echo " <li>总用户数: $(getent passwd | wc -l)</li>" >> "$REPORT_FILE"
echo " <li>普通用户数: $(getent passwd | awk -F: '$3 >= 1000 && $3 < 60000' | wc -l)</li>" >> "$REPORT_FILE"
echo " <li>系统用户数: $(getent passwd | awk -F: '$3 < 1000' | wc -l)</li>" >> "$REPORT_FILE"
echo " <li>当前登录用户数: $(who | wc -l)</li>" >> "$REPORT_FILE"
echo " </ul>" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
echo "</body>" >> "$REPORT_FILE"
echo "</html>" >> "$REPORT_FILE"
echo "HTML报告已生成: $REPORT_FILE"
finger命令是Unix系统的早期工具之一:
| 用途 | 命令示例 |
|---|---|
| 显示所有登录用户 | finger |
| 简短格式显示 | finger -s |
| 长格式显示用户信息 | finger -l |
| 查询特定用户 | finger john |
| 不显示.plan文件 | finger -p john |
| 快速模式 | finger -q |
| 只匹配登录名 | finger -m john |
| 显示空闲时间 | finger -i |
| 查看命令版本 | finger --version |
| 查看帮助 | finger --help |