`ssh <хост>` - это оболочка для входа, но `ssh <хост> <команда>` - нет?

12

Я заметил, что когда я запускаю команду непосредственно на хосте 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>только источники .bash_profile, в то время как
  2. ssh <host> <command>только источники .bashrc, что означает
  3. первая - это оболочка для входа, а вторая - нет.

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

Райан Лю
источник
выход .bashrc? Этот файл не должен выдавать никаких результатов. Любые выходные данные .bashrcмогут сломать все инструменты, использующие ssh в качестве транспорта.
Касперд
Справедливо. В этом случае пара строк .bashrcвыдает ошибку, в то время как аналогичные строки .bash_profileне были. Я воспользовался возможностью, чтобы исследовать несоответствие, прежде чем исправлять оскорбительные строки.
Райан Лу

Ответы:

12

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 обычно не вызывают оболочку с этими параметрами и не позволяют их указывать.

Эрик Ренуф
источник
«... выполняется на удаленном хосте вместо оболочки входа в систему». Я не понимаю эту дихотомию. Команда выполняется на удаленном хосте, а не в оболочке входа , или команда выполняется на удаленном хосте, вместо того , чтобы там выполнялась оболочка входа ? Если первое, как оно или / или? (разве это не обычно оба? ) Если последний, он все еще выполняется в контексте некоторой оболочки, не так ли? (интерактивный, не входящий в систему?) Так что мой вопрос также касается семантики - что означает «оболочка входа в систему», и почему OpenSSH должен быть разработан, чтобы не создавать ее для отдельных команд?
Райан Лю
@RyanLue Каждый из различных «разновидностей» оболочек делает определенные задачи более легкими / более безопасными / оптимизированными и т. Д. Хотя выполнение sshи требует входа в систему, разработчики, по-видимому, решили, что при некоторых обстоятельствах, например, запрашивая выполнение команды и возвращение, делают нет необходимости / выгоды от дополнительных шагов, которые выполняет оболочка входа в систему, и поэтому они пропускают это. Так что, действительно, есть оболочка, которая запускается, я полагаю, в основном, для настройки среды, и поскольку оболочка не будет предоставлена ​​пользователю, который вошел в систему, они обрабатывают ее так, как если бы пользователь только что запустил новую оболочку для запуска этой среды. команда
Эрик Ренуф,
«Так что, действительно, существует оболочка, которую я запускаю, я полагаю, в основном, для настройки среды ...» <, но я просто экспериментировал с этим, и оказалось, что ssh <host> <command>она не наследует среду какой-либо существующей оболочки входа в систему. Например, $ ssh <host> \$PATHвозвращает путь таким, каким он был бы без источников .bash_profile(или .profileкак бы) ... В практическом смысле, почему вы хотите обойти этот шаг?
Райан Лю
«... разработчики, по-видимому, решили, что при некоторых обстоятельствах, например, при запросе на выполнение команды и возврате, не нужно / не нужно извлекать выгоду из дополнительных шагов, которые выполняет оболочка входа в систему, и поэтому они пропускают это». <Кроме того, специально ищет разъяснения / понимание этого выбора дизайна. Я определяю мой PATHин .profile- это не то, что именно такого рода вещи вы хотите загружен перед запуском произвольной команды на удаленном хосте?
Райан Лю
1
@RyanLue Сервер Boks ssh различает использование ssh и может предоставлять разрешения для каждого из них. Удаленный вход в систему, удаленное выполнение, удаленное копирование. Возможно, это помогает понять, почему вы будете вести себя так, как вы описали. Удаленный вход в систему (интерактивное использование) может оказаться слишком сложным в среде с высоким уровнем безопасности. Openssh может быть ограничен использованием rbash / rksh и 'logout' в .bash_profile или chroot.
bbaassssiiee
4

Почему такое поведение лежит на более низкий уровне , чем оболочки: 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, но она есть, если вы когда-нибудь найдете.

zwol
источник
1

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

/unix/170493/login-non-login-and-interactive-non-interactive-shells

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

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

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

Дженаро Моралес
источник
Хорошо, но это поднимает интересный вопрос: .bashrcможет быть написан так, чтобы не быть источником, если он вызывается в неинтерактивном контексте ( т. Е. Если нет «быстрой инструкции» / $PS1переменной). Но ssh <host> <command> это определенно не интерактивный ; то есть, он не поднимет командную строку. Так почему же OpenSSH должен быть создан для создания интерактивного приглашения без входа в систему (которое пытается получить источник .bashrc) для этого, казалось бы, неинтерактивного сценария использования?
Райан Лу