/bin/bash -i перезаписывает PS1

#python #python-3.x #bash #shell #subprocess

#питон #python-3.x #bash #оболочка #подпроцесс #python

Вопрос:

Я использую следующий код python3.6 ( g.py ) для запуска интерактивной оболочки bash с настраиваемым приглашением:

 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 переменная env пуста.
  • В macOS это работает как по волшебству.

Комментарии:

1. Вам, вероятно , потребуется использовать --noprofile и --norc , чтобы избежать возможности того, что какие-либо файлы конфигурации после запуска переопределят заданную вами среду. В противном случае вы находитесь во власти того, что эти файлы решат сделать.

2. Я в любом случае не знаю, как отключить файл инициализации системного уровня, не отключая также файл инициализации пользовательского уровня.

Ответ №1:

По умолчанию bash не имеет общесистемного файла конфигурации для интерактивных оболочек. Но есть возможность добавить его во время компиляции, в config-top.h :

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

Если это включено (как я полагаю, в Debian), то, похоже, нет способа отключить это во время выполнения, не отключив также ~/.bashrc .

Debian /etc/bash.bashrc заменяет любое унаследованное значение PS1 своим собственным значением. Конечно, вы можете переопределить это в своем собственном ~/.bashrc , но это означает, что вы не можете принудительно вводить значение PS1 через среду при запуске интерактивной оболочки для кого-то другого. В конце концов, это выбор пользователя, как выглядит его приглашение, а не ваш.

Обходным путем может быть предоставление вашего собственного rcfile, который явно использует ~/.bashrc файл пользователя, а затем устанавливает запрос таким, каким вы хотите, чтобы он был. Я не знаю ни одного простого способа сделать это без временного файла:

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

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

Комментарии:

1. Я пытаюсь изменить первую строку на 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-}" ] amp;amp; [ "$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
  

Комментарии:

1. Да, я только что обнаружил эту строку. /etc/profile выполняется при запуске всех интерактивных оболочек? даже те, которые запущены пользователем, не являющимся root? Это первый файл, который будет запущен? Можем ли мы отключить это без изменения /etc файлов, чтобы скрипт python работал?

2. /etc/profile вероятно, это не имеет значения; Я думаю, что bash может быть настроен во время компиляции для обработки /etc/bash.bashrc как эквивалент на системном уровне ~/.bashrc : если он существует, он поступает при запуске интерактивной оболочки.

3. Обратите внимание: /etc/profile не следует устанавливать PS1 , по крайней мере, не использовать bash специфические функции, такие как u , потому что все оболочки POSIX используют /etc/profile , а не только bash . В идеале, /etc/bash.bashrc было бы установлено только PS1 , если бы было обнаружено, что оно еще не установлено.

4. @machine424 /etc/profile следует запускать только для оболочек входа. Я просто указывал, что /etc/bash.bashrc это источник /etc/profile .

5. Но пользователь не запускает оболочку входа, поэтому это не имеет отношения к вопросу. Проблема в том, что Debian bash скомпилирован для создания файла конфигурации всей системы для интерактивных оболочек без входа в систему.