简体   繁体   English

如何在脚本本身内重定向整个 shell 脚本的 output? ......有一个转折

[英]How to redirect output of an entire shell script within the script itself? ... with a twist

I have seen this (and I upvoted it), but it falls a bit short from my needs because:我已经看到了这个(并且我赞成它),但它离我的需求有点不足,因为:

  • I have to I need to give on-terminal feedback (that is easy, just | tee /dev/tty )我必须提供终端反馈(这很简单,只需| tee /dev/tty
  • I have to get input from users in several ways:我必须通过几种方式从用户那里获得输入:
    • read -p 'prompt: ' var
    • select yn in "Yes" "No"; do...
    • git clone from private repository asking user/pass git clone询问用户/密码

How can I do this (especially the select stuff)?我该怎么做(尤其是select的东西)?

My current test setup (cut down to size) is:我当前的测试设置(缩小尺寸)是:

#/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

This has all said defects:这具有所有缺陷:

  1. read -p prompts are not seen on terminal (but are in log file)在终端上看不到read -p提示(但在日志文件中)
  2. select yn in "Yes" "No" prompts are not seen on terminal (but are in log file); select yn in "Yes" "No"提示在终端上看不到(但在日志文件中); this is unsurprising as select doesn't accept redirection.这不足为奇,因为select不接受重定向。
  3. git clone prompt for user/pass are not seen on terminal. git clone提示。

How can I fix this?我怎样才能解决这个问题?

read -p and select both output their prompts to standard error. read -pselect都是 output 他们对标准错误的提示。 Make sure you're capturing the right stream if you want to copy their prompts to both the terminal and a file.如果您想将他们的提示复制到终端和文件中,请确保您捕获的是正确的 stream。 For example:例如:

read -p 'enter your EMAIL address: ' email | tee /dev/tty # prompt doesn't get duplicated
read -p 'enter your EMAIL address: ' email 2>&1 | tee /dev/tty # prompt does get duplicated

###
# Note: These cases might get a bit annoying because the redirection
# applies to both the prompt and everything inside the select statement
# You may have to do some additional redirection inside the select
# statement to make everything work exactly the way you want
###
select yn in "Yes" "No" ; do
  break
done | tee /dev/tty # prompt does not get duplicated

select yn in "Yes" "No" ; do
  break
done 2>&1 | tee /dev/tty # prompt does get duplicated

git clone might be more complicated. git clone可能更复杂。 If it's using something like OpenSSH under the covers to perform ssh operations then it could be writing directly to the TTY so you can't redirect its prompts just by redirecting standard out or standard error.如果它在幕后使用类似 OpenSSH 的东西来执行 ssh 操作,那么它可能会直接写入 TTY,因此您不能仅通过重定向标准输出或标准错误来重定向它的提示。 You may have to dive into tools like expect to capture the password prompts and write them somewhere else.您可能需要深入研究诸如expect之类的工具来捕获密码提示并将它们写在其他地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM