![轻松更改交互式 bash 子 shell 上的 PS1](https://linux22.com/image/42647/%E8%BD%BB%E6%9D%BE%E6%9B%B4%E6%94%B9%E4%BA%A4%E4%BA%92%E5%BC%8F%20bash%20%E5%AD%90%20shell%20%E4%B8%8A%E7%9A%84%20PS1.png)
我遇到一种情况,我需要在一个较长的过程中向用户提供一个子 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
文件是否存在即可。