Чому віддалена команда SSH отримує меншу кількість змінних середовища, а потім при ручному запуску? [зачинено]


239

У мене є команда, яка працює добре, якщо я сшу на машину і запускаю її, але не вдається, коли я намагаюся запустити її за допомогою віддаленої команди ssh, наприклад:

ssh user@IP <command>

Порівнюючи вихід "env" за допомогою обох методів, перезавантажується в різних середовищах. Коли я вручну входжу в систему на машині і запускаю env, я отримую набагато більше змінних середовища, ніж тоді, коли запускаю:

ssh user@IP "env"

Будь-яка ідея чому?


30
Чому саме це питання закрите як поза темою?
jottr

13
Можливо, тому, що це не пов'язано з програмуванням. Його слід було перемістити до Super User замість закритого.
Даніель Н

8
bashце не сценарна мова?
Дан Ніссенбаум

У Debian 8 мені довелося чомусь змінити оболонку, щоб залити / etc / passwd. Навіть перенастроювання тире, щоб дозволити / бін / ш вказати на баш, не допомогло.
користувач1050755

Відповіді:


173

Існують різні типи оболонок. Оболонка виконання команд SSH - це неінтерактивна оболонка, тоді як ваша звичайна оболонка - або оболонка для входу, або інтерактивна оболонка. Опис випливає з man bash:

       Оболонка для входу - це та, чий перший символ аргументується
       нуль - це - або починається з опції --login.

       Інтерактивна оболонка - це запускається без необов'язкових варіантів
       аргументи і без параметра -c, стандартний вхід якого
       і помилка обоє підключені до клем (як визначено)
       by isatty (3)), або той, що розпочався з опції -i. PS1 є
       set і $ - включає i, якщо bash є інтерактивним, що дозволяє a
       скрипт оболонки або файл запуску для перевірки цього стану.

       У наступних параграфах описано, як bash виконує його
       файли запуску. Якщо будь-який з файлів існує, але не може бути
       читати, bash повідомляє про помилку. Тильди розширені у файлі
       імена, як описано нижче в розділі Розширення Tilde в
       Розширення розділу.

       Коли bash викликається як інтерактивна оболонка входу, або як
       неінтерактивна оболонка з опцією --login, спочатку
       читає і виконує команди з файлу / etc / profile, якщо
       цей файл існує. Прочитавши цей файл, він шукає
       ~ / .bash_profile, ~ / .bash_login та ~ / .profile, в цьому
       впорядковує, і читає та виконує команди з першого
       що існує і читається. Опція --noprofile може
       використовувати, коли оболонка починає гальмувати цю поведінку
       ior.

       Коли оболонка входу виходить, bash читає та виконує команди
       з файлу ~ / .bash_logout, якщо він існує.

       Коли інтерактивна оболонка, яка не є оболонкою для входу, є
       запущено, bash читає та виконує команди з ~ / .bashrc,
       якщо цей файл існує. Це може бути пригнічено за допомогою
       --norc варіант. Параметр файлу --rcfile змусить баш
       читати та виконувати команди з файлу замість
       ~ / .bashrc.

       Коли bash запускається неінтерактивно, для запуску оболонки
       наприклад, скрипт шукає змінну BASH_ENV в
       навколишнє середовище, розширює свою цінність, якщо вона з’являється там,
       і використовує розширене значення як ім'я файлу для читання
       і виконати. Bash поводиться так, ніби наступна команда
       були виконані:
              if [-n "$ BASH_ENV"]; тоді . "$ BASH_ENV"; фі
       але значення змінної PATH не використовується для пошуку
       для імені файлу.


7
Чудова відповідь, саме в цьому і полягала проблема, необхідні змінні середовища знаходилися в / etc / bashrc, яка не отримується в неінтерактивному режимі. Переміщення їх у / etc / profile вирішило проблему. Велике спасибі!
Том Фейнер

1
Ця відповідь лише часткове рішення. Ось додаткова інформація: додайте іншу змінну середовища (наприклад, експорт SOURCED_SYSTEM_ETC_BASHRC) до різних файлів, які отримуються: / etc / profile, тощо / bashrc, ~ / .profile, ~ / .bash_profile, ~ / bashrc. Тоді шукайте цю унікальну змінну у висновку Дженкінса. У моєму випадку я оновив / etc / bashrc, щоб містити "експортувати SOURCED_SYSTEM_ETC_BASHRC = так", і ця змінна з'явилася у журналі Дженкінса для вузла. Тож у моєму випадку, щоб встановити змінні середовища для рабів-джинків, вони повинні входити в / etc / bashrc. Jenkins ssh тільки для входу / etc / bashrc.
Coder Roadie

Виправлення: я мав на увазі /etc/bash.bashrc, а не / etc / bashrc.
Coder Roadie

37
Це досить стінка тексту, я думаю, варто було б виділити те ssh user@host "bash --login -c 'command arg1 ...'", що змусить віддалений оболонку створити середовище входу. У розділі, який ви цитували, згадується, --loginале було б легко пропустити це.
кодовий борд

Дякую за цю публікацію, я ssh <ssh options> <IP> bash --login my_script.shзапускав сценарій на віддаленій машині, працює ласощі та дав мені змогу успішно використовувати місцеві env vars на кшталтJAVA_HOME
markc

117

Як щодо пошуку профілю перед запуском команди?

ssh user@host "source /etc/profile; /path/script.sh"

Ви можете виявити , що краще змінити , що ~/.bash_profile, ~/.bashrcабо будь-який інший .

(Як тут (linuxquestions.org) )


1
Якщо була ця проблема, це рішення спрацювало чудово.
Сам152,

10
Необхідно завжди вводити додатковий код лише для джерела оточення - це смішно!
Майкл

4
Рідко багато разів вводити такі речі, зазвичай це було б в рамках сценарію, і як таке, не важливо, скільки "зайвого коду" існує, поки він працює: tm:
Ian Vaughan

1
Якщо я надсилаю і / etc / profile, і ~ / .bash_profile (щоб отримати додатки для користувача до шляху), він працює, але це некрасиво. Повинен бути простіший спосіб сказати команді (в моєму випадку xterm) використовувати "інтерактивний" логін і закінчити повний специфічний для користувача шлях на віддаленій машині?
Джесс

ssh $ 1 "source ~ / .bashrc; ~ / temp_unix.sh" Тут temp_unix.sh експортує MANI_HOME = "mani deepak", але він не працює.
mani deepak

90

Середовище оболонки не завантажується при виконанні віддаленої команди ssh. Ви можете редагувати файл середовища ssh:

vi ~/.ssh/environment

Його формат:

VAR1=VALUE1
VAR2=VALUE2

Також перевірте sshdконфігурацію для PermitUserEnvironment=yesпараметра.


1
досконалість! +100, якщо я міг :)
Декстер

VisualGDB не вдається з помилкою "bash: gcc: команда не знайдена", і це рішення усунуло це.
KalenGi

фантастичний. Бажаю, що я знав про це років тому.
гравітація

Це ідеальна відповідь!
Jirapong

1
@ pg2455, хоча ви не завжди можете налаштувати sshd на своєму сервері (або не хочете його ввімкнути для всіх), ви все ще можете редагувати своє середовище користувача
dpedro

63

У мене було подібне питання, але врешті-решт я дізнався, що ~ / .bashrc - це все, що мені потрібно.

Однак в Ubuntu мені довелося коментувати рядок, який припиняє обробку ~ / .bashrc:

#If not running interactively, don't do anything
[ -z "$PS1" ] && return

8
Крім того, ви можете просто поставити весь "неінтерактивний" код над цим рядком.
machineghost

прекрасно, врятувало мені багато часу :) дякую
Ленс Поллард

Дякую. Тільки додавши, що файл із заявою return можна знайти на /etc/bash.bashrc.
adarshr

Чи все-таки можна обійти цей код на сервері, не змінюючи його?
Йоні

Я витратив стільки часу, намагаючись зрозуміти, чому мій сценарій не працює. Хто думав, що було б гарною ідеєю розмістити ці рядки у .bashrc ???
Шарку

4

Я вирішив, що вирішити цю проблему було просто - додати джерело / тощо / профіль у верхню частину файлу script.sh, який я намагався запустити в цільовій системі. У системах, що тут, це призвело до того, що змінні середовища, які були потрібні script.sh, були налаштовані так, ніби працює з оболонки входу.

В одній з попередніх відповідей було запропоновано використовувати ~ / .bashr_profile тощо .... Я не витрачав на це багато часу, але проблема з цим полягає в тому, що якщо ви шукаєте інший користувач цільової системи, ніж оболонка вихідної системи, з якої ви входите, мені здалося, що це викликає користувача вихідної системи ім'я, яке буде використано для ~.


Ідеально! Гарне однолінійне рішення проблеми.
corpico

3

Просто експортуйте змінні середовища, які ви хочете, вище чека на неінтерактивну оболонку в ~ / .bashrc.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.