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

如何在Shell脚本内重定向全量输出并保留终端交互?

问题:如何在整体重定向输出的脚本中保留终端交互能力

需求说明

  • 需要向终端输出反馈(已尝试| tee /dev/tty)
  • 需要支持多种用户输入方式:
    • read -p 'prompt: ' var
    • select yn in "Yes" "No"; do ...
    • 私有仓库git clone时的账号密码输入

当前测试脚本(精简版)

#/bin/bash
set -e
set -x
{
if lxc list | grep container
then
  :
else
  lxc launch images:ubuntu/20.04 container
  echo 'waiting for networking to be up-and-running...' | tee /dev/tty
  sleep 5
  echo 'installing base system...' | tee /dev/tty
  lxc exec container -- apt update
  lxc exec container -- apt install -y git
  echo "install documentation processor? " | tee /dev/tty
  select yn in "Yes" "No"
  do
    if [ $yn == "Yes" ]
    then
      echo 'installing documentation processor...' | tee /dev/tty
      lxc exec container -- apt install -y wget
      lxc exec container -- wget https://github.com/plantuml/plantuml/releases/download/v1.2022.12/plantuml-1.2022.12.jar -O /usr/local/bin/plantuml.jar
    fi
    break
  done
  read -p 'enter your EMAIL address: ' email | tee /dev/tty
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git config --global user.email "$email"
  read -p 'enter your FULL NAME: ' name | tee /dev/tty
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git config --global user.name "$name"
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git config --global credential.helper store
  echo 'cloning repository...' | tee /dev/tty
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git clone git@github.com:gabime/spdlog.git
  echo "enable audio in container? " | tee /dev/tty
  select yn in "Yes" "No"
  do
    if [ $yn == "Yes" ]
    then
      for dev in $(find /dev/snd -type c)
      do
        lxc config device add container snd_$(basename $dev) unix-char source=$dev path=$dev gid=1000
        lxc exec container -- apt install -y alsa-utils
      done
    fi
    break
  done
fi
} >lxd_build.log 2>&1

现存问题

  • read -p的提示仅写入日志,终端不可见
  • select的交互提示仅写入日志,终端不可见
  • git clone的账号密码输入提示终端不可见

解决方案

核心思路

放弃脚本整体重定向的方式,改为区分非交互命令输出与终端交互流:非交互命令的输出定向到日志,交互相关的提示/输入直接绑定到终端,同时用tee保留终端反馈。

具体修复步骤

  1. 处理read -p提示
    read -p的提示默认输出到stderr,会被整体重定向吞掉。改为显式将提示输出到终端,再单独读取输入,最后把输入内容写入日志:
# 替代原read写法
echo -n 'enter your EMAIL address: ' > /dev/tty
read email
echo "EMAIL address entered: $email" >> lxd_build.log
  1. 处理select交互
    select依赖终端环境,需要临时将其输入输出绑定到终端,同时手动记录选择结果到日志:
# 替代原select写法
echo "install documentation processor? " > /dev/tty
# 绑定select的IO到终端
select yn in "Yes" "No"
do
  if [ "$yn" = "Yes" ]
  then
    echo 'installing documentation processor...' | tee -a lxd_build.log
    # 非交互命令输出定向到日志
    lxc exec container -- apt install -y wget >> lxd_build.log 2>&1
    lxc exec container -- wget https://github.com/plantuml/plantuml/releases/download/v1.2022.12/plantuml-1.2022.12.jar -O /usr/local/bin/plantuml.jar >> lxd_build.log 2>&1
  fi
  # 记录选择结果到日志
  echo "Selected option: $yn" >> lxd_build.log
  break
done < /dev/tty > /dev/tty 2>&1
  1. 处理git clone交互
    SSH/HTTPS方式的git clone交互需要绑定终端IO,同时可以用tee兼顾日志记录:
# 替代原git clone写法
echo 'cloning repository...' | tee -a lxd_build.log
lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git clone git@github.com:gabime/spdlog.git 2>&1 | tee -a lxd_build.log

优化后的完整脚本

#!/bin/bash
set -e
set -x

LOG_FILE="lxd_build.log"
> "$LOG_FILE" # 清空日志,如需追加改为>>

if lxc list | grep container
then
  :
else
  lxc launch images:ubuntu/20.04 container >> "$LOG_FILE" 2>&1
  echo 'waiting for networking to be up-and-running...' | tee -a "$LOG_FILE"
  sleep 5
  echo 'installing base system...' | tee -a "$LOG_FILE"
  lxc exec container -- apt update >> "$LOG_FILE" 2>&1
  lxc exec container -- apt install -y git >> "$LOG_FILE" 2>&1

  # 处理第一个select交互
  echo "install documentation processor? " > /dev/tty
  select yn in "Yes" "No"
  do
    if [ "$yn" = "Yes" ]
    then
      echo 'installing documentation processor...' | tee -a "$LOG_FILE"
      lxc exec container -- apt install -y wget >> "$LOG_FILE" 2>&1
      lxc exec container -- wget https://github.com/plantuml/plantuml/releases/download/v1.2022.12/plantuml-1.2022.12.jar -O /usr/local/bin/plantuml.jar >> "$LOG_FILE" 2>&1
    fi
    echo "Selected option for documentation processor: $yn" >> "$LOG_FILE"
    break
  done < /dev/tty > /dev/tty 2>&1

  # 处理email输入
  echo -n 'enter your EMAIL address: ' > /dev/tty
  read email
  echo "enter your EMAIL address: $email" >> "$LOG_FILE"
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git config --global user.email "$email" >> "$LOG_FILE" 2>&1

  # 处理姓名输入
  echo -n 'enter your FULL NAME: ' > /dev/tty
  read name
  echo "enter your FULL NAME: $name" >> "$LOG_FILE"
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git config --global user.name "$name" >> "$LOG_FILE" 2>&1

  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git config --global credential.helper store >> "$LOG_FILE" 2>&1

  # 处理git clone
  echo 'cloning repository...' | tee -a "$LOG_FILE"
  lxc exec container --user 1000 --group 1000 --cwd /home/ubuntu --env HOME=/home/ubuntu -- git clone git@github.com:gabime/spdlog.git 2>&1 | tee -a "$LOG_FILE"

  # 处理第二个select交互
  echo "enable audio in container? " > /dev/tty
  select yn in "Yes" "No"
  do
    if [ "$yn" = "Yes" ]
    then
      for dev in $(find /dev/snd -type c)
      do
        lxc config device add container snd_$(basename $dev) unix-char source=$dev path=$dev gid=1000 >> "$LOG_FILE" 2>&1
      done
      lxc exec container -- apt install -y alsa-utils >> "$LOG_FILE" 2>&1
    fi
    echo "Selected option for audio enable: $yn" >> "$LOG_FILE"
    break
  done < /dev/tty > /dev/tty 2>&1
fi

关键说明

  • 不再使用整体大括号重定向,而是逐个处理命令输出,确保交互流独立于日志流
  • tee -a $LOG_FILE实现终端反馈与日志记录的双重输出
  • 所有交互操作的IO都绑定到/dev/tty,保证提示和输入正常显示
  • 手动记录用户输入内容到日志,确保日志完整性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 09:30:55