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

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

我遇到一种情况,我需要在一个较长的过程中向用户提供一个子 shell。我想更改提示以提醒用户他们处于特殊的子 shell 中并且尚未完成其余过程。我以为这会实现我想要的......

echo "PS1='foo:'" | bash -i

但是当我输入该行时,这就是我得到的输出

me@mercury:~$ PS1='foo:'
foo:exit
me@mercury:~$ 

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

答案1

您可以使用进程替换来本质上创建一个仅在调用时存在的 ~/.bashrc ,bash -i如下所示:

 bash --rcfile <(echo "PS1='foo: '") -i

答案2

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

PROMPT_COMMAND='PS1="foo: ";unset PROMPT_COMMAND' bash

即使您的 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
)

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
)

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

答案3

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

如果调用程序提供额外的权限,您可能还需要考虑打开受限制的 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

然后打电话/bin/bash -rcfile ~/.bashrc.appsubshell -i

答案4

同意 SiegeX 的观点(他比我先一步:))

解释该行为:

如果 Bash 的标准输入和输出是普通终端,那么它只会以交互模式启动。在管道中输入初始命令时情况并非如此。

您可以使用该-c选项来提供命令,但这也排除了交互模式。

如果您确实想保留用户 rc,只需在 rcfile 字符串中添加一些测试/源语句到 source~/.bashrc以及/etc/bashrc文件是否存在即可。

相关内容