【问题标题】:/bin/bash -i overwrites PS1/bin/bash -i 覆盖 PS1
【发布时间】:2019-08-30 15:22:34
【问题描述】:

我正在使用以下 python3.6 代码 (g.py) 来启动带有自定义提示的交互式 bash shell:

import subprocess
import os                                                                         


envi = os.environ.copy() # env of the python process
envi["PS1"]="my-prompt"

s = subprocess.Popen(['/bin/bash', '-i'], env=envi, shell=False)
s.communicate()

当我在 debian stretch 9 上运行它时,我得到:

initial_prompt> ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
  206 pts/0    00:00:00 ps
initial_prompt> python3 g.py 
user123§ced47a150f0c:ß$ 
user123§ced47a150f0c:ß$ ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
  207 pts/0    00:00:00 python3
  208 pts/0    00:00:00 bash
  209 pts/0    00:00:00 ps

我得到user123§ced47a150f0c:ß$ 而不是my-prompt

  • 当我将--norc 添加到/bin/bash 时,它可以工作,但我需要阅读~/.bashrc
  • ~/.bashrc 中,PS1 未更改。我没有~/.bash_profile 文件。
  • PROMPT_COMMAND 环境变量为空。
  • 在 MacOS 上,它就像一个魅力。

【问题讨论】:

  • 您将可能需要使用--noprofile--norc 以避免任何启动后配置文件覆盖您设置的环境的可能性。否则,无论这些文件决定做什么,您都将受到摆布。
  • 我不知道要禁用系统级初始化文件而不禁用用户级初始化文件。

标签: python python-3.x bash shell subprocess


【解决方案1】:

默认情况下,bash 没有用于交互式 shell 的系统范围配置文件。但是,在config-top.h 中可以添加一个编译时选项:

/* System-wide .bashrc file for interactive shells. */
/* #define SYS_BASHRC "/etc/bash.bashrc" */

如果启用此功能(我相信它在 Debian 中),似乎无法在运行时禁用此功能,而同时禁用 ~/.bashrc

Debian 的/etc/bash.bashrc 替换 PS1 的任何继承值用它自己的值。当然,您可以在自己的~/.bashrc 中覆盖它,但这意味着在为其他人启动交互式 shell 时,您不能通过环境强制设置 PS1 的值。最后,由用户选择他们的提示是什么样的,而不是你的。

一种解决方法可能是提供您的自己的 rcfile,该文件明确地获取用户的~/.bashrc 文件,然后将提示设置为您想要的。如果没有临时文件,我不知道有什么简单的方法可以做到这一点:

with NamedTemporaryFile(mode='w+', buffering=True, delete=False) as tmprc:
    tmprc.write('. ~/.bashrc\n')
    tmprc.write('PS1="my-prompt "\n')

    s = subprocess.Popen(['/bin/bash', '-i', '--rcfile', tmprc.name])

【讨论】:

  • 我将第一行更改为with NamedTemporaryFile(mode='w+', buffering=True, delete=False) as tmprc: 但仍然无法正常工作。你试过了吗?
【解决方案2】:

在 Debian Stretch 下,PS1 设置在 /etc/bash.bashrc

# set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

这也来自/etc/profile

if [ "${PS1-}" ]; then
  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

【讨论】:

  • 是的,我刚刚发现了这条线。 /etc/profile 在所有交互式 shell 启动时运行?甚至那些由非root用户启动的?它是要运行的第一个文件吗?我们可以在不修改 /etc 文件的情况下禁用它,以便 python 脚本工作吗?
  • /etc/profile 可能不相关;我认为bash 可以在编译时配置为将/etc/bash.bashrc 视为~/.bashrc 的系统级等价物:如果存在,它是在交互式shell 启动时获取的。
  • 注意:/etc/profile 应该设置PS1,至少不使用bash 特定功能,如\u,因为所有POSIX shell 都使用@ 987654336@,不仅仅是bash。理想情况下,/etc/bash.bashrc 仅在检测到尚未设置时才会设置 PS1
  • @machine424 /etc/profile 应该只为登录 shell 运行。我只是指出/etc/bash.bashrc 来自/etc/profile
  • 但是用户没有启动一个登录shell,所以它与问题无关。问题是 Debian 的 bash 也被编译为非登录交互式 shell 的系统范围配置文件。
猜你喜欢
  • 2016-03-18
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多