You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

tty写入权限、setgid配置及用户登录时通知在线用户的方法

解决方案:实现登录时通知所有在线用户

方法一:用wall命令快速实现(最简单)

wall是系统自带的广播工具,专门用来给所有在线用户发送消息,无需处理单个终端的权限问题,直接在/etc/profile.d/login_notify.sh中写入以下脚本即可:

#!/bin/bash
# 收集登录信息
USER=$(whoami)
DATE=$(date "+%Y-%m-%d %H:%M:%S")
# 获取SSH登录IP,本地登录则显示"本地登录"
IP=$(echo "${SSH_CONNECTION:-本地登录}" | awk '{print $1}')
TTY=$(tty)

# 构造通知内容
MESSAGE="用户$USER于$DATE通过IP$IP、终端$TTY登录系统"

# 发送广播
echo "$MESSAGE" | wall

给脚本添加执行权限:

chmod +x /etc/profile.d/login_notify.sh

为什么这个方法有效?

wall默认具备向所有终端发送消息的权限,无需额外设置SUID/SGID,普通用户执行也能生效(多数系统默认允许)。唯一限制是如果用户用mesg n关闭了消息接收,会看不到通知,但这是用户级别的自主设置,不属于脚本问题。


方法二:用PAM模块以Root身份执行(最可靠)

如果wall不符合需求(比如需要自定义终端过滤),可以用PAM的pam_exec模块,确保脚本以Root身份运行,从而拥有写入所有终端的权限:

步骤1:创建通知脚本

新建/usr/local/bin/login_notify.sh,内容如下:

#!/bin/bash
# 从PAM环境变量获取登录信息
USER="$PAM_USER"
DATE=$(date "+%Y-%m-%d %H:%M:%S")
IP="${PAM_RHOST:-本地登录}"
TTY="$PAM_TTY"

MESSAGE="用户$USER于$DATE通过IP$IP、终端$TTY登录系统"

# 遍历所有在线终端并发送消息,忽略无权限的情况
for tty in $(who | awk '{print $2}'); do
    echo -e "\n$MESSAGE\n" > "/dev/$tty" 2>/dev/null
done

添加执行权限:

chmod +x /usr/local/bin/login_notify.sh

步骤2:配置PAM

编辑/etc/pam.d/login(处理本地登录)和/etc/pam.d/sshd(处理SSH登录),在文件末尾添加一行:

session optional pam_exec.so seteuid /usr/local/bin/login_notify.sh

为什么这个方法比你的SGID方案有效?

你之前尝试的SGID到tty组无效,是因为/dev/pts/*这类伪终端的所属组是登录用户的主组(而非tty组),即使脚本属于tty组也没有写入权限。而通过PAM执行脚本时,会以Root身份运行,自然拥有所有终端的写入权限。


为什么你的原方案失败?

  • /dev/pts下的伪终端设备,所属用户是当前登录的用户,所属组是该用户的主组(比如user1的组是user1),而非系统的tty组,所以SGID到tty组无法获得写入权限。
  • write命令能工作是因为它会检查目标用户的mesg设置,且内部有专门的权限校验逻辑,并非单纯依赖tty组权限。

内容的提问来源于stack exchange,提问作者FueraDeServicio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:22:58