Защо 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
Вероятно защото не е свързано с програмиране. Трябваше да бъде преместен в Super User, вместо да бъде затворен.   -  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
Този отговор е само частично решение. Ето малко повече информация: добавете различна променлива на средата (напр. експортиране на SOURCED_SYSTEM_ETC_BASHRC) към различните файлове, които се извличат: /etc/profile, etc/bashrc, ~/.profile, ~/.bash_profile, ~/bashrc. След това потърсете тази уникална променлива в изхода на Jenkins. В моя случай актуализирах /etc/bashrc, за да съдържа 'export SOURCED_SYSTEM_ETC_BASHRC=yes' и тази променлива се появи в журнала на Jenkins за възела. Така че в моя случай, за да зададете променливи на средата за jenkins slaves, те трябва да отидат в /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 за стартиране на скрипт на отдалечената машина, работи страхотно и ми позволи успешно да използвам локални env vars като 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

Shell средата не се зарежда при изпълнение на отдалечена 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: командата не е намерена и това решение поправи това. - 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
Благодаря. Само добавям, че файлът с израза за връщане може да бъде намерен на /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