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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:50:44