Почему удаленная команда SSH получает меньше переменных среды, чем при запуске вручную?

У меня есть команда, которая работает нормально, если я подключаюсь к машине по ssh и запускаю ее, но не работает, когда я пытаюсь запустить ее с помощью удаленной команды ssh, например:

ssh user@IP <command>

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

ssh user@IP "env"

Есть идеи, почему?


person Tom Feiner    schedule 19.10.2008    source источник
comment
Почему именно этот вопрос закрыт как не по теме?   -  person jottr    schedule 18.01.2014
comment
Наверное, потому, что это не связано с программированием. Его следовало переместить в суперпользователь, а не закрыть.   -  person Daniel H    schedule 07.03.2014
comment
bash не является языком сценариев?   -  person Dan Nissenbaum    schedule 06.04.2018
comment
В Debian 8 мне по какой-то причине пришлось изменить оболочку на bash в / etc / passwd. Даже переконфигурирование тире, чтобы / bin / sh указывало на bash, не помогло.   -  person user1050755    schedule 09.02.2019


Ответы (6)


Есть разные виды снарядов. Оболочка для выполнения команд SSH - это неинтерактивная оболочка, тогда как обычная оболочка является либо оболочкой входа в систему, либо интерактивной оболочкой. Описание следует из man bash:

       A  login  shell  is  one whose first character of argument
       zero is a -, or one started with the --login option.

       An interactive shell is  one  started  without  non-option
       arguments  and  without the -c option whose standard input
       and error are both connected to terminals  (as  determined
       by  isatty(3)), or one started with the -i option.  PS1 is
       set and $- includes i if bash is interactive,  allowing  a
       shell script or a startup file to test this state.

       The  following  paragraphs  describe how bash executes its
       startup files.  If any of the files exist  but  cannot  be
       read,  bash reports an error.  Tildes are expanded in file
       names as described below  under  Tilde  Expansion  in  the
       EXPANSION section.

       When  bash is invoked as an interactive login shell, or as
       a non-interactive shell with the --login option, it  first
       reads and executes commands from the file /etc/profile, if
       that file exists.  After reading that file, it  looks  for
       ~/.bash_profile,  ~/.bash_login,  and  ~/.profile, in that
       order, and reads and executes commands from the first  one
       that  exists  and is readable.  The --noprofile option may
       be used when the shell is started to inhibit  this  behav­
       ior.

       When a login shell exits, bash reads and executes commands
       from the file ~/.bash_logout, if it exists.

       When an interactive shell that is not  a  login  shell  is
       started,  bash reads and executes commands from ~/.bashrc,
       if that file exists.  This may be inhibited by  using  the
       --norc  option.   The --rcfile file option will force bash
       to  read  and  execute  commands  from  file  instead   of
       ~/.bashrc.

       When  bash  is  started  non-interactively, to run a shell
       script, for example, it looks for the variable BASH_ENV in
       the  environment,  expands  its value if it appears there,
       and uses the expanded value as the name of a file to  read
       and  execute.   Bash  behaves  as if the following command
       were executed:
              if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
       but the value of the PATH variable is not used  to  search
       for the file name.

person Vinko Vrsalovic    schedule 19.10.2008
comment
Отличный ответ, именно в этом и заключалась проблема, необходимые переменные среды находились в / etc / bashrc, который не был получен в неинтерактивном режиме. Перемещение их в / etc / profile решило проблему. Большое спасибо! - person Tom Feiner; 19.10.2008
comment
Это лишь частичный ответ. Вот еще немного информации: добавьте другую переменную среды (например, export SOURCED_SYSTEM_ETC_BASHRC) в различные файлы, которые будут получены: / etc / profile, etc / bashrc, ~ / .profile, ~ / .bash_profile, ~ / bashrc. Затем найдите эту уникальную переменную в выводе Jenkins. В моем случае я обновил / etc / bashrc, чтобы он содержал «export SOURCED_SYSTEM_ETC_BASHRC = yes», и эта переменная появилась в журнале Jenkins для узла. Итак, в моем случае, чтобы установить переменные среды для ведомых устройств jenkins, они должны войти в / etc / bashrc. Jenkins ssh login только из / etc / bashrc. - person Coder Roadie; 04.05.2016
comment
Исправление: я имел в виду /etc/bash.bashrc, а не / etc / bashrc. - person Coder Roadie; 04.05.2016
comment
Это настоящая стена текста, я думаю, стоит выделить, что ssh user@host "bash --login -c 'command arg1 ...'" заставит удаленную оболочку настроить среду входа в систему. В процитированном вами разделе упоминается --login, но это легко упустить из виду. - person codebeard; 24.11.2016
comment
Спасибо за этот пост, я использовал ssh <ssh options> <IP> bash --login my_script.sh для запуска сценария на удаленном компьютере, работал неплохо и позволил мне успешно использовать локальные переменные окружения, такие как JAVA_HOME - person markc; 03.01.2020
comment
В некоторых системах UNIX (например, AIX) добавление переменных среды в /etc/profile не поможет, но /etc/environment работает. - person R.Liu; 11.12.2020

Как насчет источника профиля перед запуском команды?

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

Возможно, вам будет лучше изменить это на ~/.bash_profile, ~/.bashrc или что-то еще.

(Как здесь (linuxquestions. org))

person Ian Vaughan    schedule 24.09.2009
comment
Если бы эта проблема была, это решение отлично работало. - person Sam152; 25.05.2011
comment
Необходимость всегда вводить дополнительный код только для того, чтобы исходить из среды, просто смешно! - person Michael; 08.01.2013
comment
Редко можно повторно набирать такие вещи, обычно это происходит в сценарии, и поэтому не имеет значения, сколько там дополнительного кода, пока он работает: tm: - person Ian Vaughan; 08.01.2013
comment
Если я использую как / etc / profile, так и ~ / .bash_profile (чтобы получить пользовательские дополнения к пути), он работает, но это некрасиво. Должен быть более простой способ указать команде (в моем случае xterm) использовать интерактивный вход и получить полный путь для конкретного пользователя на удаленном компьютере? - person Jess; 04.04.2013
comment
ssh $ 1 источник ~ / .bashrc; ~ / temp_unix.sh Здесь temp_unix.sh имеет экспорт MANI_HOME = mani deepak, но он не работает. - person mani deepak; 25.03.2014
comment
Ура, мужик, это было для меня - person MikeW; 04.09.2014
comment
Еще один полезный рабочий процесс (если script1.sh исходит из script2.sh): scp script1.sh script2.sh user@host:/tmp/, за которым следует ssh user@host "cd /tmp/ && ./script1.sh" - person blong; 13.08.2015
comment
Может быть трудно решить, какой bashrc или bash_profile скрипт необходимо использовать. Вместо этого пусть bash справится с этим сам: ssh user@host "bash --login -c 'command arg1 ...'" - person codebeard; 24.11.2016
comment
Добавление . /etc/profile && nextCommand помогло. Я обнаружил, что будет чище, если я буду использовать bash -s < myscript вместо того, чтобы вводить одну команду за другой, имея необходимость экранировать символы. Попробуйте . /etc/profile && env увидеть загруженные переменные. - person ; 23.01.2017
comment
Это не работает на моем сервере. Странно, но если я сделаю ssh usr@host "export PATH=blablabla$PATH;env", это сработает. - person Tamaki Sakura; 23.01.2019

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

vi ~/.ssh/environment

Его формат:

VAR1=VALUE1
VAR2=VALUE2

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

person dpedro    schedule 03.04.2012
comment
совершенство! +100, если бы я мог :) - person Dexter; 14.09.2012
comment
VisualGDB не работал с ошибкой bash: gcc: command not found, и это решение исправило это. - person KalenGi; 20.02.2013
comment
фантастика. Хотел бы я знать об этом много лет назад. - person gravitation; 17.03.2013
comment
Это прекрасный ответ! - person Jirapong; 27.08.2015
comment
Я не понимал, чем .ssh/environment может быть полезным, но полностью понимал PermitUserEnvironment=yes. Хороший! - person pg2455; 19.03.2019
comment
@ pg2455, хотя вы не всегда можете настроить sshd на своем сервере (или не хотите включать его для всех), вы все равно можете редактировать свою пользовательскую среду - person dpedro; 19.03.2019
comment
хорошо сработал для меня - person Amit P; 01.04.2019
comment
Однако, когда я добавляю свою установку git в PATH, другие обычные двоичные файлы не идентифицируются, как ls, cd и т. Д. - person Amit P; 01.04.2019

У меня была аналогичная проблема, но в конце концов я обнаружил, что ~ / .bashrc - это все, что мне нужно.

Однако в Ubuntu мне пришлось прокомментировать строку, прекращающую обработку ~ / .bashrc:

#If not running interactively, don't do anything
[ -z "$PS1" ] && return
person tomaszbak    schedule 13.11.2010
comment
В качестве альтернативы вы можете просто поместить весь свой неинтерактивный код над этой строкой. - person machineghost; 26.06.2012
comment
красивая, сэкономила много времени :) спасибо - person Lance Pollard; 13.09.2013
comment
Спасибо. Просто добавим, что файл с оператором return можно найти по адресу /etc/bash.bashrc. - person adarshr; 11.08.2014
comment
Есть ли способ обойти этот код на сервере, не меняя его? - person Yoni; 31.07.2016
comment
Я потратил так много времени, пытаясь понять, почему мой сценарий не работает. Кто подумал, что поместить эти строчки в .bashrc - хорошая идея ??? - person Sharcoux; 31.05.2018

Я нашел простое решение этой проблемы - добавить источник / etc / profile в начало файла script.sh, который я пытался запустить в целевой системе. В представленных здесь системах это привело к тому, что переменные среды, необходимые для script.sh, были настроены так, как если бы они выполнялись из оболочки входа в систему.

В одном из предыдущих ответов предлагалось использовать ~ / .bashr_profile и т. Д. Я не тратил на это много времени, но проблема в том, что если вы используете ssh для другого пользователя в целевой системе, чем оболочка в исходной системе, из которой вы входите в систему, мне показалось, что это вызывает пользователя исходной системы имя, которое будет использоваться для ~.

person Chuck    schedule 05.01.2011
comment
Идеально! Красивое однострочное решение проблемы. - person corpico; 07.04.2017

Просто экспортируйте нужные вам переменные среды выше проверки для неинтерактивной оболочки в ~ / .bashrc.

person Michael MacDonald    schedule 15.02.2012