轻松更改交互式 bash 子外壳上的 PS1

use*_*455 9 bash

我有一种情况,我需要在漫长的过程中途向用户提供一个子外壳。我想更改提示以提醒用户他们在一个特殊的子 shell 中并且还没有完成其余的过程。我以为这会做我想做的......

echo "PS1='foo:'" | bash -i
Run Code Online (Sandbox Code Playgroud)

但是当我进入那行时,这是我得到的输出

me@mercury:~$ PS1='foo:'
foo:exit
me@mercury:~$ 
Run Code Online (Sandbox Code Playgroud)

有没有简单的方法来解决这个问题?我可以编写自己的自定义 bashrc...但我更愿意保留用户通常的 bash-shell 设置。

Sie*_*geX 14

您可以使用进程替换来创建一个只存在于bash -i调用中的 ~/.bashrc ,如下所示:

 bash --rcfile <(echo "PS1='foo: '") -i
Run Code Online (Sandbox Code Playgroud)


Arc*_*ege 9

我认为使用env PS1="foo: " /bin/bash --norc -i而不是使用--rcfile选项会更好。环境被保留,不会被点文件覆盖,并且在进入 shell 之前设置了 PS1 环境变量。

如果调用程序提供额外的权限,您可能还想考虑打开一个受限的 shell。env PS1="foo: " PATH=$RESTRICTED_PATH /bin/rbash --norc -i对于 $RESTRICTED_PATH 所需的任何值。

或者有一个已经预制的 bashrc 文件:

if [ -f /etc/bashrc ]; then
    source /etc/bashrc
fi
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi
PS1="foo:"
PATH=$RESTRICTED_PATH
Run Code Online (Sandbox Code Playgroud)

然后调用 /bin/bash -rcfile ~/.bashrc.appsubshell -i


Sté*_*las 9

如果您仍然希望~/.bashrc读取并假设~/.bashrc未设置$PROMPT_COMMAND,则可以使用以下技巧:

PROMPT_COMMAND='PS1="foo: ";unset PROMPT_COMMAND' bash
Run Code Online (Sandbox Code Playgroud)

即使您的 rc 文件设置$PS1并且$PROMPT_COMMAND将执行(从 zsh/bash/ksh93 shell)这样的事情的另一种方法:

(
  export IN_FD
  exec {IN_FD}<&0
  echo 'PS1="foo: "; exec <&"$IN_FD" {IN_FD}<&-' | bash -i
)
Run Code Online (Sandbox Code Playgroud)

那是PS1="foo: "通过管道馈送,然后告诉bash将标准输入切换到原始标准输入。

这具有在 stderr 上显示提示和命令行的副作用。你可以解决它:

(
  export IN_FD ERR_FD
  exec {IN_FD}<&0 {ERR_FD}>&2 2> /dev/null
  echo 'PS1="foo: "; exec <&"$IN_FD" {IN_FD}<&- 2>&"$ERR_FD" {ERR_FD}>&-' |
    bash -i
)
Run Code Online (Sandbox Code Playgroud)

尽管这有隐藏启动文件输出的错误消息(如果有)的副作用。