Почему Bash не может найти команду, даже если $ PATH указан правильно?

9

Я указываю путь к моей команде в файле / etc / profile :

export PATH=$PATH:/usr/app/cpn/bin

Моя команда находится в:

$ which ydisplay 
/usr/app/cpn/bin/ydisplay

Итак, когда я выполняю «echo $ PATH», вывод выглядит так:

$ echo $PATH
...:/usr/app/cpn/bin

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

$ ssh 127.0.0.1 ydisplay
$ bash: ydisplay: command not found

Но мой путь все еще присутствует:

$ ssh 127.0.0.1 echo $PATH
...:/usr/app/cpn/bin

Пожалуйста, объясните мне, почему Bash не может найти ydisplay во время сеанса SSH и как правильно настроить SSH, чтобы избежать этой проблемы.

Более того, если я укажу $ PATH в локальном файле .bashrc у текущего пользователя, все будет работать правильно. Но я хочу изменить только один файл, указав множество файлов для каждого пользователя. Вот почему я спрашиваю.

SIGSEGV
источник
1
работает бег ydisplay? делает ssh 127.0.0.1 /usr/app/cpn/bin/ydisplayработу?
Bananguin
@ user1129682 Да, ydisplay с полным указанным именем работает и только ydisplay работает
SIGSEGV
Когда вы не зарегистрированы (у вас нет удаленного сеанса), а только отправляете команду удаленно, у вас нет доступа к переменным среды таким же образом, потому что ваши файлы .bashrc / .profile не выполняются. Это причина того, что они отвечают за установку переменных для текущего сеанса.
Mnmnc
14
Просто примечание: ssh 127.0.0.1 echo $PATHне делайте то, что, как вы думаете, делает: оболочка расширяет $ PATH еще до того, как ssh выполнится, так что ничего не доказывает и не опровергает.
Ульрих Шварц

Ответы:

5

ТЛ; др

Работающие ssh 127.0.0.1 ydisplayисточники, ~/.bashrcа не /etc/profile. ~/.bashrcВместо этого измените свой путь .

подробности

Единственный раз , когда /etc/profileчитается, когда ваша оболочка является «Войти оболочки».

Из справочного руководства Bash :

Когда bash вызывается как оболочка входа в систему, ... он сначала читает и выполняет команды из файла / etc / profile

Но при запуске ssh 127.0.0.1 ydisplay, bashне запускается в качестве оболочки. Тем не менее, он читает другой файл запуска. Bash Reference Manual говорит:

когда ... исполняется ... sshd. ... он читает и выполняет команды из~/.bashrc

Таким образом, вы должны ввести свои PATHнастройки ~/.bashrc.

В большинстве систем ~/.bash_profileисточники ~/.bashrc, поэтому вы можете поместить свои настройки только ~/.bashrcвместо того, чтобы помещать их в оба файла.

Там нет никакого стандартного способа изменить настройки для всех пользователей, но большинство систем имеют /etc/bashrc, /etc/bash.bashrcили аналогичные.

В противном случае настройте pam_envи вставьте PATHнастройки /etc/environment.

Смотрите также:

Mikel
источник
1

Исторически файлы профиля ( /etc/profileи ~/.profile) вызывались при входе в систему (в текстовой консоли, что еще?) И служили многим целям:

  • Установите переменные окружения и другие параметры (например, umask) для сеанса.
  • Запустите дополнительные программы в начале сеанса (например, уведомление по электронной почте).
  • Запустите программу для сеанса, если она отличается от оболочки (например, другой оболочки или X Window).
  • Установите параметры терминала (например stty).
  • Установите параметры оболочки (например, псевдонимы).

Все эти цели не были определены как отдельные до позже. Поскольку сценарии профиля могут делать вещи, которые имеют смысл только в интерактивном сеансе (взаимодействие с терминалом, запуск других программ), когда был введен удаленный вызов оболочки ( rsh ), представители rsh решили не вызывать удаленную оболочку в качестве оболочки входа в систему, так что сценарии профиля не выполняются. (В некоторых версиях rshdесть возможность запускать удаленную оболочку в качестве оболочки входа в систему.) Ssh скопировал это поведение для замены rsh.

Если вы хотите, чтобы выполнялись сценарии вашего профиля, вы можете явно вызывать их.

ssh 127.0.0.1 '. /etc/profile; . ~/.profile; ydisplay'

Обратите внимание на команду .для загрузки скриптов профиля внутри оболочки: это команды, которые должны выполняться внутри этой оболочки, а не внешняя программа.

Если вы хотите установить глобальную переменную среды для всех пользователей, во многих системах есть другой метод: вместо того, чтобы определять его в /etc/profile, определите его в /etc/environment. Этот файл читается через pam_envмодуль; большинство дистрибутивов Linux настроены на его чтение.

Если ваша оболочка входа в систему bash, есть еще одна возможность. Как правило, вы не должны устанавливать переменные среды в.bashrc (потому что они не будут установлены в сеансах X, за исключением случаев, когда вы проходите через терминал с интерактивной оболочкой, потому что они не будут установлены, если вы входите в систему интерактивно на текстовой консоли или более ssh, потому что они переопределят пользовательские настройки, если вы вызовете оболочку внутри другой программы). Однако, у bash есть странная особенность, которую я никогда не понимал: она читается ~/.bashrcв двух не связанных между собой обстоятельствах:

  • в интерактивных оболочках, которые не являются оболочками входа в систему;
  • в неинтерактивных оболочках, которые не являются оболочками входа в систему, если bash считает, что она была вызвана rshdили sshd.

Когда вы запускаете команду через ssh, вы находитесь во втором случае. Вы можете сделать так, чтобы ваш профиль читали, читая /etc/profileи .profileот .bashrc. Включите следующий код в свой ~/.bashrc:

case $- in
  *i*) :;; # this is an interactive shell, fine
  *) # This is not an interactive shell! This must be a non-interactive remote shell session.
    . /etc/profile; . ~/.profile
    return;;
esac
Жиль "ТАК - перестань быть злым"
источник