10

Я заметил, что когда я запускаю команду непосредственно на хосте SSH с использованием синтаксиса ssh <host> <command> , я вижу вывод .bashrc но не вывод .bash_profile (или .profile).

Например, если я помещу следующую команду вверху обоих файлов,

echo ${BASH_SOURCE[0]}

и вручную источник .bash_profile (который источники .bashrc в свою очередь), я посмотрю

$ . .bash_profile
.bash_profile
.bashrc

Это тот же вывод, который я вижу, если я подключаюсь к этому компьютеру удаленно через SSH, используя форму команды ssh <host> . (И если я временно утащу .bash_profile где-нибудь еще, ни одна из этих строк не отобразится.)

Тем не менее, если я выполнить команду непосредственно на удаленной машине с ssh <host> <command> форма ssh то результат выглядит следующим образом :

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

Насколько я понимаю, разница между .bash_profile и .bashrc заключается в том, что первый предназначен для оболочек входа в систему, а второй - для интерактивных оболочек без входа в систему.

Я заключил следующее:

  1. ssh <host> source только .bash_profile , в то время как
  2. ssh <host> <command> только исходники .bashrc , что означает
  3. первая - это оболочка для входа, а вторая - нет.

Верны ли эти выводы? Почему ssh <host> <command> рассматривается как интерактивная оболочка, не входящая в систему? Разве SSH все еще не подключается к удаленной машине, чтобы выполнить команду?

3 ответа3

11

OpenSSH (скорее всего, то, что вы используете) решает, создавать ли оболочку входа в систему или нет, и делает это только в том случае, если вы не запускаете определенную команду. От man ssh:

 If command is specified, it is executed on the remote host instead of a
 login shell.

Таким образом, для сервера ssh это выбор реализации: хочет ли он создать оболочку входа или нет, и если вы даете команду на запуск, он этого не делает.

В то время как ssh выполняет вход в систему, если вы выполняете команду и завершаете работу, на самом деле это гораздо больше похоже на создание оболочки для простого запуска этой команды, чем на получение среды входа в систему. Кажется, учитывая это, что люди, пишущие OpenSSH, решили относиться к этому как к такой задаче.

Они создают неинтерактивную, не входящую в систему оболочку для выполнения команды, потому что это дух запуска команды в другом контексте / оболочке. Обычно, однако, неинтерактивные оболочки не будут автоматически ~/.bashrc что явно происходит здесь. bash действительно пытается помочь нам здесь. Из документов

Вызывается демоном удаленной оболочки

Bash пытается определить, когда он запускается со стандартным входом, подключенным к сетевому соединению, как при выполнении демоном удаленной оболочки, обычно rshd, или демоном защищенной оболочки sshd. Если Bash определяет, что он выполняется таким образом, он читает и выполняет команды из ~/.bashrc, если этот файл существует и доступен для чтения. Он не будет делать это, если вызывается как sh. Параметр --norc можно использовать для запрета этого поведения, а параметр --rcfile можно использовать для принудительного чтения другого файла, но ни rshd, ни sshd обычно не вызывают оболочку с этими параметрами и не позволяют их указывать.

3

Причина такого поведения лежит на более низком уровне, чем в оболочках: ssh host (случай "оболочки входа в систему") использует псевдотерминал на удаленном хосте для связи между процессом сервера sshd и оболочкой; Вместо этого ssh host command sshd использует каналы между command и командой . Псевдотерминалы необходимы для интерактивного использования интерпретатора команд, такого как оболочка, или режима « read-eval-print » языка сценариев; они реализуют множество удобных для человека функций, таких как возможность опровергать опечатки. Но они имеют больше накладных расходов и (в зависимости от конфигурации) не позволяют произвольным данным проходить без изменений, поэтому SSH избегает их использования, когда взаимодействие не происходит.

Иногда команда SSH / эвристика команд не понимает этого; его можно переопределить с помощью ключей -t и -T . Например, чтобы войти на удаленный компьютер и немедленно подключить приостановленный сеанс screen , вам нужно выполнить ssh -t host screen -R ; ssh host screen -R заставит screen жаловаться на то, что он не подключен к терминалу. Я не могу вспомнить ситуацию, когда вы на самом деле захотите использовать -T , но она есть, если вы когда-нибудь ее найдете.

1

Сначала вы должны увидеть различные типы, вы можете прочитать это:

https://unix.stackexchange.com/questions/170493/login-non-login-and-interactive-non-interactive-shells

Теперь, если вы откроете свой bashrc, вы увидите в начале это:

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

Это означает, что в зависимости от того, как вы обращаетесь к системе, этот файл загружает код внутри или нет.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .