我有一种情况,我需要在漫长的过程中途向用户提供一个子外壳。我想更改提示以提醒用户他们在一个特殊的子 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)
我认为使用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
如果您仍然希望~/.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)
尽管这有隐藏启动文件输出的错误消息(如果有)的副作用。