Вопрос или проблема
Я не могу скопировать файл по scp, когда файл .bashrc удаленной машины включает команду source для обновления путей и некоторых переменных. Почему это происходит?
Вам следует сделать так, чтобы часть или все ваши .bashrc
не выполнялась, когда ваша оболочка не интерактивна. (Команда scp
является примером вызова не интерактивной оболочки, если кто-то радикально не изменил ваши системы.) Затем положите все команды, которые могут генерировать вывод, в этот раздел файла.
Стандартный способ сделать это в инициализационном файле:
# Поместите все команды здесь, которые должны выполняться независимо от того,
# является ли это интерактивной или не интерактивной оболочкой.
# Пример команды:
umask 0027
# проверьте, не установлена ли переменная приглашения, и также, чтобы предотвратить сбои
# когда `$PS1` не установлена и используется `set -u`
if [ -z "${PS1:-}" ]; then
# переменная приглашения не установлена, значит, это *не* интерактивная оболочка
return
fi
# Если мы достигли этой строки кода, значит, переменная приглашения установлена, так что
# это интерактивная оболочка.
# Поместите все команды здесь, которые должны выполняться только если это
# интерактивная оболочка.
# Пример команды:
echo "Добро пожаловать, ${USER}. Это файл ~/.bashrc."
Вы также можете увидеть, как люди используют
[ -z "${PS1:-}" ] && return
вместо моего более многословного if
выражения.
Если вы не хотите перестраивать весь файл, вы также можете просто сделать так, чтобы определенные строки выполнялись только в интерактивном контексте, заключив их так:
if [ -n "${PS1:-}" ]; then
echo "Эта строка выполняется только в интерактивном режиме."
fi
Если вы таким образом сегрегируете свой .bashrc
, то ваши команды scp
больше не должны сталкиваться с этой проблемой.
Это решение сработало и для меня. Но поскольку моя оболочка по умолчанию – TCSH, я немного изменил решение следующим образом (в .tcshrc):
if ( $?SSH_TTY ) then
exec /bin/bash
endif
Просто решил поделиться для пользы всех.
Добавляя к отличному предложению Vijay, я бы также рекомендовал добавить setenv SHELL /usr/bin/bash
, то есть
if ( $?SSH_TTY ) then
setenv SHELL /usr/bash
exec /bin/bash
endif
В моем случае exec bash
не устанавливает переменную окружения SHELL
, мой .bashrc
тоже ее не устанавливал, и некоторые программы начали работать неправильно, когда переменная SHELL
не соответствовала фактически используемой оболочке (в моем случае rocgdb
).
Ответ или решение
Когда вы пытаетесь выполнить команду scp
для копирования файлов на удалённую машину, которая имеет в своём файле .bashrc
команды source
, могут возникнуть проблемы. Давайте разберем, почему это происходит и как можно решить эту проблему.
Причины возникновения проблемы
-
Неинтерактивный режим:
scp
использует неинтерактивный режим оболочки для выполнения операций, что подразумевает отсутствие интерактивного командного ввода. В результате, некоторые команды, которые выведены в.bashrc
, могут не выполняться должным образом или вызывать ошибки. -
Выполнение
source
: Если в файле.bashrc
используются командыsource
, которые загружают .sh скрипты или устанавливают переменные окружения только для интерактивных сеансов, это может вызвать проблемы при выполнении команд в неинтерактивной среде. Например, если скрипт, загружаемый с помощьюsource
, требует пользовательского ввода или пытается использовать переменные среды, которые не инициализируются в неинтерактивной сессии.
Рекомендации по исправлению
Для избежания проблем при запуске неинтерактивной оболочки с scp
, следует изменить структуру вашего файла .bashrc
, чтобы команды, которые должны выполняться исключительно в интерактивном сеансе, не запускались в неинтерактивном.
Пример корректной настройки .bashrc
# Команды, которые должны выполняться всегда
umask 0027
# Проверяем, есть ли переменная PS1 (отличает интерактивную и неинтерактивную оболочку)
if [ -z "${PS1:-}" ]; then
return
fi
# Тут размещаем команды, которые должны выполняться только в интерактивной оболочке
echo "Добро пожаловать, ${USER}."
Альтернативный подход
Если вам не нужно переписывать весь файл, можно просто обернуть специфические строки условием:
if [ -n "${PS1:-}" ]; then
echo "Эта строка выполняется только в интерактивном режиме."
fi
Пара специфических примеров для TCSH
Если ваша основная оболочка — TCSH, вы можете применить следующий подход в вашем файле .tcshrc
:
if ( $?SSH_TTY ) then
setenv SHELL /usr/bin/bash
exec /bin/bash
endif
Таким образом, вы не только переключаете оболочку, но и устанавливаете переменную окружения SHELL
, что может быть важно для некоторых программ, требующих соответствия вашей текущей оболочки с переменной SHELL
.
Заключение
Неправильная конфигурация файла .bashrc
может привести к проблемам при выполнении scp
из-за особенностей работы с интерактивными и неинтерактивными режимами. Разделение инструкций в зависимости от типа оболочки поможет вам избежать потенциальных ошибок и повысить надёжность работы ваших скриптов и процессов. Надеюсь, это руководство поможет вам правильно конфигурировать вашу командную оболочку и обеспечить безошибочную работу команд scp
.