使用mkfifo管道在Bash脚本中实现用户列表实时同步的问题
问题描述
我正在编写一款用于管理用户和用户组的Bash脚本,希望在特定标签页中添加或删除用户后,能自动重新加载当前所有用户列表。我尝试用mkfifo管道实现,但只有重启应用时才会重载列表。以下是我的代码:
mkfifo "$fpipe" trap "rm -f $fpipe $fts" EXIT fpipe="OUTPUT.txt" #getAllUsers function function get_all_user(){ echo -e '\f' >> "$fpipe" alluser=$(cat /etc/passwd | awk -F: '$7=="/bin/bash" {print $1"\\n"$3"\\n"$4"\\n"}' | tr -d '[:space:]' ) echo -e $alluser > "$fpipe" } export -f get_all_user #get_selected_user function function get_selected_user() { echo -e '\f' > "$temp" echo "$1" > "$temp" cat $temp } export -f get_selected_user #adduser function function run_adduser() { # check for this in '/etc/passwd' and '/etc/shadow' # $2 is the username # $3 is the password if id "$2" &>/dev/null; then zenity --warning \ --text="Username existed. Please enter another username." else useradd -m -p $(openssl passwd -1 $3) -s /bin/bash -G sudo $2 zenity --info \ --text="User added successfully." fi } export -f run_adduser # Users information tab get_all_user yad --plug=$KEY --tabnum=1 --width=600 --height=450 --expand-column=0 --limit=10 \ --list --select-action='@bash -c "get_selected_user %s %s %s"' --column="Username" --column="UID" --column="GID" <&3 & exec 3>&-
解决思路
1. 修复FIFO管道的核心逻辑
你当前代码里先创建了FIFO管道,随后又把fpipe变量覆盖为普通文件OUTPUT.txt,直接废掉了FIFO的实时监听能力。正确做法是保持FIFO的使用:
# 定义FIFO路径,避免和普通文件冲突 fpipe="/tmp/user_list_fifo" mkfifo "$fpipe" # 脚本退出时清理FIFO trap "rm -f $fpipe" EXIT
同时让Yad列表控件直接从FIFO持续读取数据,而非一次性读取:
yad --plug=$KEY --tabnum=1 --width=600 --height=450 --expand-column=0 --limit=10 \ --list --select-action='@bash -c "get_selected_user %s %s %s"' --column="Username" --column="UID" --column="GID" < "$fpipe" &
2. 用户操作后主动触发列表刷新
在run_adduser的成功分支里,直接调用get_all_user更新FIFO内容,Yad会自动读取新数据并刷新列表:
function run_adduser() { if id "$2" &>/dev/null; then zenity --warning \ --text="Username existed. Please enter another username." else useradd -m -p $(openssl passwd -1 $3) -s /bin/bash -G sudo $2 zenity --info \ --text="User added successfully." # 触发列表刷新 get_all_user fi }
3. 修正用户列表的输出格式
当前get_all_user里的tr -d '[:space:]'会破坏列结构,导致Yad无法识别三列数据。改用awk直接输出正确的制表符分隔格式:
function get_all_user(){ # 发送换页符清空现有列表 echo -e '\f' > "$fpipe" # 按列输出用户数据,制表符分隔 awk -F: '$7=="/bin/bash" {print $1 "\t" $3 "\t" $4}' /etc/passwd > "$fpipe" }
4. 确保Yad插件模式的关联正确
如果使用多标签主窗口,要保证主窗口的--key参数和插件的--plug=$KEY完全对应,且主窗口需等待插件进程,避免提前退出导致列表失效。
内容的提问来源于stack exchange,提问作者Ngọc Hưng
相关产品推荐
相关产品推荐

