Привет,
Я пытаюсь загрузить файл .bashrc (т.е. источник /home/ubuntu/.bashrc) при запуске команды запуска fab, чтобы добавить некоторые переменные среды и расширить переменную пути:
запустить ('источник /home/ubuntu/.bashrc && echo $ PATH')
Это показывает мне только:
[[email protected]] выход: / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / игры: / usr / местные / игры
вместо гораздо более длинного списка путей, который я вижу при входе на удаленный сервер вручную.
Как мне заставить fab правильно импортировать файл .bashrc в мой удаленный домашний каталог?
Спасибо!
Это крутая штука, а не фантастика.
Какие файлы bash решает использовать при запуске, может быть сложно http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html, а debian / ubuntu (и большинство дистрибутивов) имеют некоторую настройку в /etc/profile
и по умолчанию ~/.bashrc
.
По умолчанию fab использует оболочку /bin/bash -l -c
, а -l
делает ее оболочкой «входа в систему». Без настройки debian / ubuntu оболочка «входа в систему» bash может получить ~/.bash_profile
но не ~/.bashrc
.
Но в ubuntu 16.04 он, похоже, по умолчанию использует .bashrc
даже для оболочки входа. Но строки, добавленные в нижней части значения по умолчанию .bashrc
, не обрабатываются, потому что он отключается вверху, если обнаруживает, что он работает не интерактивно.
Здесь я добавил две строки к пользователю ubuntu-16.04 по умолчанию .bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
export VAR1=val1
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
export VAR2=val2
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
...
Вот файл, с которым я тестирую:
from fabric.api import run, env, task
<strong i="23">@task</strong>
def get_myvars():
run("echo VAR1=$VAR1 VAR2=$VAR2")
Результаты, достижения:
$ fab -H testpy05.ec2.st-av.net get_myvars
[testpy05.ec2.st-av.net] Executing task 'get_myvars'
[testpy05.ec2.st-av.net] run: echo VAR1=$VAR1 VAR2=$VAR2
[testpy05.ec2.st-av.net] out: VAR1=val1 VAR2=
[testpy05.ec2.st-av.net] out:
...
С первого взгляда звучит нормально, спасибо @ploxiln!
Спасибо за развернутый ответ!
Похоже, что это отличается от стандартного поведения ssh, и его было трудно отладить. Когда я вручную ssh'd, все работало нормально, тогда как ткань имела другое значение PATH из-за того, что не запускал .bash_profile в OSX.
@bitprophet это может быть ошибка OSX ??
@ code-tree Вы используете Fabric 1 или 2? 1.x использует явные оболочки оболочки, поэтому он отличается от стандартного клиента OpenSSH; версия 2 не выполняет обертывания и должна вести себя как клиент OpenSSH с точки зрения того, что sshd запускает от вашего имени.
Версия 1 имеет несколько параметров конфигурации env для изменения этой оболочки оболочки, поэтому вы можете попробовать добавить к ней флаги, например -i
который IIRC является bash для «запуска интерактивного режима и источника дополнительных файлов».
Это странно, потому что я использую версию 2.2.1
. В настоящее время мне нужно сделать следующее, чтобы мое приложение заработало:
c.run('bash -l -c "python3 ./configure.py"')
Как и когда я установил Python 3, он добавил себя в PATH через мой .bash_profile
, который не запускается Fabric. Я также не вносил никаких изменений в стандартную встроенную конфигурацию sshd.
Тогда это странно, мне нужно посмотреть, смогу ли я воспроизвести. Просто провел быструю трассировку вменяемости, чтобы доказать, что я имею в виду, re: Fabric 2 не делает ничего "особенного", управляемого re: sshd:
command
command
ssh myserver <command>
, предположительно@ code-tree также, если можете, опубликуйте более подробную информацию о том, что именно вы используете, и другие детали среды (клиентская и серверная ОС / версия и т. д.).
Конечно, я использую старую версию OSX в качестве сервера. Если вы можете подтвердить, что все работает нормально на более новой MacOS, тогда ладно. Но если нет, то может быть проблема с MacOS как сервером в целом?
Боковое примечание, мне интересно, действительно ли это случай неправильного диагноза:
ткань имела другое значение PATH из-за того, что не запущен .bash_profile в OSX
Может ли это быть примером # 1744, где Fabric 2 отличается от ssh
с точки зрения шунтирования локальных переменных окружения по трубе? (Зависит от конкретных переменных env, о которых идет речь, и от того, могут ли они быть похожими локально и удаленно; @code-tree может легко опровергнуть эту теорию, дважды проверив точные значения в игре re: их локальный и удаленный bash_profile ... 😁)
Но я все равно собираюсь устранить эту неполадку, просто чтобы я знал, что я не сумасшедший, re: мое понимание того, что делает sshd с точки зрения оболочек и исходных файлов.
Также мне интересно, связано ли это со сценарием / интеллектом из # 1816, который также относится к оболочкам и файлам запуска. Это _ вероятно_ не имеет прямого отношения из-за утверждения здесь о том, что ssh
ведет себя одним способом, а Fabric ведет себя иначе (в отличие от того, «как sshd обычно вызывает оболочку»), но в любом случае стоит связать.
Обнаружил, что пытался наткнуться на кучу глубоких погружений в код sshd, которые я помню, как делал в последние несколько месяцев, связанных с чем-то в этом направлении. Я не могу найти его сейчас, что меня раздражает. РЕДАКТИРОВАТЬ: ах, я думаю, что это была не связанная с Paramiko проблема (не связывание, потому что нет смысла сбивать с толку) выполнение команд перед аутентификацией. OK.
Хорошо, так что же на самом деле происходит, когда мы запрашиваем команду exec?
shell
(который загружает определенную пользователем программу оболочки входа и не принимает никаких command
), либо канал exec
запрос (который просто говорит "выполняет заданную командную строку, которая может содержать путь" и не указывает больше)775f8a23f2353f5869003c57a213d14b28e0736e
)Ну, сначала я немного пошутлюсь. Запуск с произвольным контейнером Debian 8.10 (на котором запущен OpenSSH 6.7!) Я вижу это в журналах уровня DEBUG3 после выполнения ssh localhost whoami
:
debug1: server_input_channel_req: channel 0 request exec reply 1
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req exec
Starting session: command for root from 172.17.0.1 port 42598
Выполнение fab -H localhost -- whoami
:
debug1: server_input_channel_req: channel 0 request exec reply 1
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req exec
Starting session: command for root from 172.17.0.1 port 42610
Хорошо, они оба делают exec
... этого и следовало ожидать. Что-нибудь изменилось в дереве процессов? не должно быть, и ... нет. оба выглядят так:
sshd,1 -D -e
└─sshd,1535
└─pstree,1537 -alpU
Значит, в игре точно нет оболочки? Что он вообще делает? Могу ли я использовать такие вещи, как &&
?
Я могу! например, whoami && id
отлично работает. Это немного странно, учитывая мое понимание управления процессами Unix; кажется маловероятным, что sshd буквально выполняет exec(string)
, но если бы он использовал оболочку для интерпретации, разве мы не увидели бы это в pstree
?
Думаю, пора по-настоящему покопаться в openssh-portable и посмотреть, что к чему.
session_input_channel_req
, в (как вы уже догадались) session_input_channel_req , которая регистрирует, а затем отправляет различным функциям в зависимости от типа сеанса (оболочка, открытие pty, exec, подсистема и т. Д.)exec
что означает session_exec_reqdo_exec_pty
или (в нашем случае, потому что мы не запрашивали pty; вы можете сказать, потому что в строках журнала нет информации о номере tty) do_exec_no_ptyКроме того, я _did_ сделал часть этой трассировки (но по другой причине / фокусу) в прошлом, как в декабре 2016 года: https://github.com/paramiko/paramiko/pull/398#issuecomment -264281759. Совершенно забыл ...
Причина, по которой я не вижу оболочку в pstree
, связана с использованием execve
, который заменяет родительский процесс вместо порождения дочернего. Хорошо знать. (РЕДАКТИРОВАТЬ: неправильно, это просто заменяет дочерний процесс sshd оболочкой; сама оболочка может также выполнять вызов exec в стиле replace-me; см. Комментарии ниже.)
Во всяком случае так! Это по-прежнему должно означать, что клиенты Fabric и OpenSSH делают одно и то же с точки зрения выполнения оболочки; ничто из того, что они делают, не изменило бы эти части кодовой базы OpenSSH. Это всегда должно быть что-то вроде bash -c "python3 ./configure.py"
, с фактическим значением bash
зависимости от пользователя уровня macOS @code-tree и его настроенной оболочки.
Это заставляет меня задаться вопросом, верна ли моя догадка о передаче env var как дифференциатора, поскольку это единственное, о чем я могу думать о re: как две среды выполнения могут различаться. FWIW в моем тестировании, ориентированном на интерфейс командной строки, env
сообщает об одном и том же в обеих системах, и независимо от этих других проблем, связанных с env, поведение _default_ (из-за политики безопасности SSH) всегда должно заключаться в том, что локальный env не "просачивается" в Обратная сторона.
Да, я почти уверен, что sshd всегда запускает командную строку в оболочке пользователя (настроенной в / etc / passwd). Однако он добавляет к командной строке "exec", если он может проанализировать командную строку и определить, что это единственная команда.
$ ssh testdeploy02.ec2.st-av.net pstree -a
...
|-sshd -D
| `-sshd
| `-sshd
| `-pstree -a
$ ssh testdeploy02.ec2.st-av.net 'pstree -a && sleep 1'
...
|-sshd -D
| `-sshd
| `-sshd
| `-bash -c pstree -a && sleep 1
| `-pstree -a
$ ssh testdeploy02.ec2.st-av.net 'VAR=-a sh -c "exec pstree \$VAR"'
...
|-sshd -D
| `-sshd
| `-sshd
| `-pstree -a
Что касается переменных среды, они в основном контролируются конфигурациями клиента ssh и сервера sshd:
$ grep Env /etc/ssh/*_config
/etc/ssh/ssh_config: SendEnv LANG LC_*
/etc/ssh/sshd_config:AcceptEnv LANG LC_*
Таким образом, клиент ssh явно отправляет некоторые переменные (вне самой командной строки), и они фильтруются sshd. Но, видимо, есть исключения:
$ ssh testdeploy02.ec2.st-av.net env | grep TERM
$ ssh -t testdeploy02.ec2.st-av.net env | grep TERM
TERM=xterm-256color
На самом деле я думаю, что поведение «автоматический exec для замены оболочки одной командой» - это особенность bash:
$ dash -c "pstree -a"
...
├─sshd -D
│ └─sshd
│ └─sshd
│ └─bash
│ └─dash -c pstree -a
│ └─pstree -a
$ bash -c "pstree -a"
├─sshd -D
│ └─sshd
│ └─sshd
│ └─bash
│ └─pstree -a
РЕДАКТИРОВАТЬ: Для полноты:
$ bash -c "pstree -a && sleep 1"
├─sshd -D
│ └─sshd
│ └─sshd
│ └─bash
│ └─bash -c pstree -a && sleep 1
│ └─pstree -a
Ах да, я ошибся, execve
просто означает, что дочерний процесс -c xxx
. Мои тесты были в zsh, fwiw.
Также @ploxiln да, вещь с env vars ссылается на другие билеты, указанные выше, хотя еще неизвестно, действительно ли @code-tree испытывает другой симптом, чем те.
Извините, я думаю, что это ложная тревога. Я не знал, что есть какая-либо разница между выполнением команды через ssh inline и выполнением после входа в систему через ssh. Когда я делаю ssh host 'echo $PATH'
он также не обновляет PATH, где echo $PATH
после входа в систему работает нормально.
Я до сих пор не понимаю, почему ssh это делает (похоже, мне действительно нужно сделать ssh host 'bash -l -c "python3 ./configure.py"'
). Тем не менее, можно с уверенностью сказать, что это не проблема Fabric. Извините за путаницу.
@code-tree это связано с тем, что было упомянуто ранее - оболочки имеют несколько разных режимов, в которых они работают, часто называемые 'логином' и 'интерактивным' (и обычно они находятся поверх базового режима, который не считается ни тем, ни другим) и какой режим оболочка запускается, изменяет набор загружаемых rc-файлов.
Важным моментом здесь является то, что bash -c xxx
не считается "интерактивным" и поэтому пропускает загрузку определенных файлов - например, .bash_profile
- а просто запускает bash
без -c
обычно интерактивен и загружает файлы профиля.
Как вы видели выше, sshd всегда запускает bash -c <command send down the pipe>
когда вы просите его запустить одну команду (как это делает Fabric или как ssh host command
), и, таким образом, всегда находится в неинтерактивном режиме. (Если вы не сделаете то, что делает Fabric 1, и не запустите свою собственную вложенную оболочку с -l
... но тогда вы используете bash -c "bash -l -c \"oh god escaping is hard help\""
и я собираюсь попробовать 🥃 сейчас.
В любом случае, не все потеряно, мне нужно обновлять память об этой части вещей каждые несколько лет, очевидно, так что э-э ... теперь я освежился 😆
Это крутая штука, а не фантастика.
Какие файлы bash решает использовать при запуске, может быть сложно http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html, а debian / ubuntu (и большинство дистрибутивов) имеют некоторую настройку в
/etc/profile
и по умолчанию~/.bashrc
.По умолчанию fab использует оболочку
/bin/bash -l -c
, а-l
делает ее оболочкой «входа в систему». Без настройки debian / ubuntu оболочка «входа в систему» bash может получить~/.bash_profile
но не~/.bashrc
.Но в ubuntu 16.04 он, похоже, по умолчанию использует
.bashrc
даже для оболочки входа. Но строки, добавленные в нижней части значения по умолчанию.bashrc
, не обрабатываются, потому что он отключается вверху, если обнаруживает, что он работает не интерактивно.Здесь я добавил две строки к пользователю ubuntu-16.04 по умолчанию
.bashrc
# ~/.bashrc: executed by bash(1) for non-login shells. # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) # for examples export VAR1=val1 # If not running interactively, don't do anything case $- in *i*) ;; *) return;; esac export VAR2=val2 # don't put duplicate lines or lines starting with space in the history. # See bash(1) for more options HISTCONTROL=ignoreboth ...
Вот файл, с которым я тестирую:
from fabric.api import run, env, task <strong i="24">@task</strong> def get_myvars(): run("echo VAR1=$VAR1 VAR2=$VAR2")
Результаты, достижения:
$ fab -H testpy05.ec2.st-av.net get_myvars [testpy05.ec2.st-av.net] Executing task 'get_myvars' [testpy05.ec2.st-av.net] run: echo VAR1=$VAR1 VAR2=$VAR2 [testpy05.ec2.st-av.net] out: VAR1=val1 VAR2= [testpy05.ec2.st-av.net] out: ...
Вы спасли мою жизнь. Это идеальный ответ, который я нахожу :) Большое спасибо!
Самый полезный комментарий
Это крутая штука, а не фантастика.
Какие файлы bash решает использовать при запуске, может быть сложно http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html, а debian / ubuntu (и большинство дистрибутивов) имеют некоторую настройку в
/etc/profile
и по умолчанию~/.bashrc
.По умолчанию fab использует оболочку
/bin/bash -l -c
, а-l
делает ее оболочкой «входа в систему». Без настройки debian / ubuntu оболочка «входа в систему» bash может получить~/.bash_profile
но не~/.bashrc
.Но в ubuntu 16.04 он, похоже, по умолчанию использует
.bashrc
даже для оболочки входа. Но строки, добавленные в нижней части значения по умолчанию.bashrc
, не обрабатываются, потому что он отключается вверху, если обнаруживает, что он работает не интерактивно.Здесь я добавил две строки к пользователю ubuntu-16.04 по умолчанию
.bashrc
Вот файл, с которым я тестирую:
Результаты, достижения: