/etc/profile.d и "ssh -t"
Я хотел запустить скрипт на удаленной машине. Простое решение заключается в следующем:
ssh remote1 some-script
Это работает до тех пор, пока удаленный скрипт не захочет подключиться к другому удаленному компьютеру (remote2), который требует интерактивной аутентификации, как это (remote2 доступен только через remote1 в этом случае):
ssh remote1 "ssh remote2 some-script"
Решение проблемы заключается в использовании -t вариант для сш.
ssh -t remote1 "ssh remote2 some-script"
Это работает, но я получаю пробемы в случае, если я использую это (где some-script может выполнить дальнейшие команды ssh):
ssh -t remote1 some-script
Я обнаружил, что некоторые переменные среды не установлены, которые устанавливаются, когда я не использую -t вариант. Эти переменные окружения устанавливаются в сценариях /etc/profile.d, Я думаю, что эти сценарии не запускаются по какой-то причине, если использовать -t вариант, но запускаются, если я им не пользуюсь.
В чем причина этого? Есть ли способ обойти это? Я использую SUSE Linux (версия 10).
Изменить: я сделал некоторые дополнительные исследования. Я поместил несколько строк вывода в следующие места:
- в одном файле в
/etc/profile.d - в
~/.bash_profile(файла не было раньше) - в
~/.bashrc(файла не было раньше)
Затем я проверил несколько сценариев, какой вывод я получаю и в каком порядке (переменная окружения, которую я проверял, $PATH):
ssh remote1:profile.d,.bashrc,.bash_profile,$PATHХОРОШО.ssh -t remote1:profile.d,.bashrc,.bash_profile,$PATHХОРОШО.ssh remote1 echo '$PATH': только.bashrc,$PATHХОРОШО.ssh -t remote1 echo '$PATH': нет вывода скрипта.$PATHNOK.
Теперь я действительно не понимаю, что происходит. Если я запускаю интерактивную оболочку, все, кажется, работает нормально (хотя я нахожу странным, что ~/.bashrc включен до ~/.bash_profile). Если я запускаю неинтерактивную оболочку без -tСценарии профиля, кажется, не работают, но переменные среды установлены. Если я запускаю неинтерактивную оболочку с -t, тогда профили профилей не выполняются и переменные среды не устанавливаются. У кого-нибудь есть объяснение этому?
3 ответа
Я не нашел причину проблемы. Может быть, это специально для платформы (SLES 10 или вариант, который я использую). Я нашел обходной путь вместо этого:
ssh -t remote1 "/bin/bash --login -c some-script"
Это заставляет оболочку входа в систему, которая запускает скрипты профиля.
На все вопросы вы можете найти ответы в разделе "ПРИЗНАНИЕ" справочной страницы bash:
Когда bash вызывается как интерактивная оболочка входа в систему или как неинтерактивная оболочка с параметром --login, она сначала читает и выполняет команды из файла /etc/profile, если этот файл существует. После прочтения этого файла он ищет ~/.bash_profile, ~/.bash_login и ~/.profile в указанном порядке, а также читает и выполняет команды из первой, которая существует и доступна для чтения. Опция --noprofile может использоваться, когда оболочка запущена, чтобы запретить это поведение.
Когда оболочка входа в систему закрывается, bash читает и выполняет команды из файла ~/.bash_logout, если он существует.
Когда запускается интерактивная оболочка, которая не является оболочкой входа в систему, bash читает и выполняет команды из ~/.bashrc, если этот файл существует. Это может быть запрещено с помощью параметра --norc. Опция --rcfile file заставит bash читать и выполнять команды из файла вместо ~/.bashrc.
Как видите, интерактивные оболочки только источник .bashrcи часто .bash_profile будет получен оттуда, что объясняет порядок, который вы видите.
Очень часто эти файлы также имеют условие, чтобы анализировать только определенные разделы только для интерактивных оболочек ([[ $- == *i* ]]), что объясняет, почему некоторые части могут отсутствовать для неинтерактивных оболочек.
Разница между
ssh remote1 echo '$PATH'
а также
ssh -t remote1 echo '$PATH'
также объясняется на странице руководства bash:
Bash пытается определить, когда он запускается со своим стандартным входом, подключенным к сетевому соединению, как при выполнении демоном удаленной оболочки, обычно
rshdили демон безопасной оболочкиsshd, Если bash определяет, что он выполняется таким образом, он читает и выполняет команды из~/.bashrc[Я предполагаю, что следует прочитать/etc/bash.bashrc] а также~/.bashrc, если эти файлы существуют и доступны для чтения.
В первом примере bashsdin подключен к сетевому соединению, поэтому он работает ~/.bashrc, Во-вторых, его stdin исходит от псевдо-терминала, так что это не так.