#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
скомпилирован для создания файла конфигурации всей системы для интерактивных оболочек без входа в систему.