SCP завершился неудачно без ошибки.

Вопрос или проблема

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

$ scp test.txt 192.168.0.2:~
[email protected]'s password: 
 ________________________________________

Когда я устанавливаю SSH-соединение, используя Midnight Commander, и копирую файлы, всё работает.

Некоторая информация о моей машине:

$ ssh -V
OpenSSH_5.8p1 Debian-1ubuntu3, OpenSSL 0.9.8o 01 Jun 2010

$ uname -a
Linux squatpc 2.6.38-10-generic #46-Ubuntu SMP Tue Jun 28 15:05:41 UTC 2011 i686 i686 i386 GNU/Linux

Я использую Kubuntu 11.04.

Редактирование: Дополнительная информация по просьбе комментариев:

$ scp -v test.txt 192.168.0.2:~
Executing: program /usr/bin/ssh host 192.168.0.2, user (unspecified), command scp -v -t -- ~
OpenSSH_5.8p1 Debian-1ubuntu3, OpenSSL 0.9.8o 01 Jun 2010
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to 192.168.0.2 [192.168.0.2] port 22.
debug1: Connection established.
debug1: identity file /home/job/.ssh/id_rsa type 1
debug1: Checking blacklist file /usr/share/ssh/blacklist.RSA-2048
debug1: Checking blacklist file /etc/ssh/blacklist.RSA-2048
debug1: identity file /home/job/.ssh/id_rsa-cert type -1
debug1: identity file /home/job/.ssh/id_dsa type -1
debug1: identity file /home/job/.ssh/id_dsa-cert type -1
debug1: identity file /home/job/.ssh/id_ecdsa type -1
debug1: identity file /home/job/.ssh/id_ecdsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.8p1 Debian-1ubuntu3
debug1: match: OpenSSH_5.8p1 Debian-1ubuntu3 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.8p1 Debian-1ubuntu3
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ECDSA 28:f3:2b:31:36:43:9b:07:d8:33:ca:43:4f:ca:6c:4c
debug1: Host '192.168.0.2' is known and matches the ECDSA host key.
debug1: Found key in /home/job/.ssh/known_hosts:20
debug1: ssh_ecdsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/job/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/job/.ssh/id_dsa
debug1: Trying private key: /home/job/.ssh/id_ecdsa
debug1: Next authentication method: password
[email protected]'s password: 
debug1: Authentication succeeded (password).
Authenticated to 192.168.0.2 ([192.168.0.2]:22).
debug1: channel 0: new [client-session]
debug1: Requesting [email protected]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
debug1: Sending command: scp -v -t -- ~
 ________________________________________
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 2120, received 1872 bytes, in 0.3 seconds
Bytes per second: sent 7783.1, received 6872.6
debug1: Exit status 0

и

$ type scp
scp is hashed (/usr/bin/scp)

Ха-ха, только что выяснил, в чем проблема.

Поскольку мне так нравятся коровы, я добавил fortune | cowsay в начало моего файла .bashrc, который при запуске bash выдает следующий вывод:

 _______________________________________
< Вы потеряете важный файл. >
 ---------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Все это прекрасно (и иногда смешно), когда bash запускается в интерактивном режиме. Однако bash читает ~/.bashrc, когда он работает в интерактивном режиме и не является логин-шеллом, или когда он является логин-шеллом и его процесс-родитель – это rshd или sshd. Когда вы запускаете scp, сервер запускает оболочку, которая запускает удалённый экземпляр scp. Вывод из .bashrc запутывает scp, так как он посылается так же, как и данные протокола scp. Очевидно, это известная ошибка, подробнее читается здесь.

Кроме того, отметьте, что подчеркивания, которые я упомянул в вопросе, это те, что в верхней строке текстового облака.

Итак, решение было простым: я добавил следующее в начало .bashrc на удалённой (целевой) машине:

# Если не интерактивный режим, ничего не делать
[[ $- == *i* ]] || return

Эта строка присутствует в .bashrc по умолчанию, но оказалась намного ниже из-за моих многочисленных (очевидно, неаккуратных) правок.

Насколько мне известно, правильный способ сделать так, чтобы scp работал без помех, больше связан не с условием для вывода на экран в вашем сценарии ~/.bashrc, а просто с ограничением вывода на экран в сценарии ~/.bash_profile. По крайней мере, так это работает в моей системе (CentOS).

Редактирование для ясности:

  1. Добавляйте в файл ~/.bashrc только те строки, которые требуются для “всех” удалённых подключений (например, установка определённых переменных окружения допустима, но вывод человекочитаемого текста – нет).
  2. Может различаться в зависимости от вашей системы

Это поведение может произойти, когда ваш файл .bashrc выводит какой-либо текст или у вас есть MOTD (Сообщение дня). Вы можете использовать опцию -o с scp:

С помощью -o вы можете передавать опции SSH, в данном случае вы можете задать опцию, такую как RequestTTY=no, и она никогда не будет запрашивать вывод терминала.

scp -o RequestTTY=no source target

@Job прав. Тем не менее, эта проблема может стать большой, если графика приветственного экрана является частью /etc/bash.bashrc.

Вы должны убедиться, что удалили такой графический контент с обоих:

  1. /etc/bash.bashrc
  2. ~/.bashrc

На системах debian и ubuntu в неинтерактивной оболочке сначала вызывается /etc/bash.bashrc, затем ~/.bashrc.

Я не уверен насчет этой ошибки с scp, давно его использовал. Я заменил scp на rsync, и это намного лучше. Rsync должен быть практически на каждом устройстве с Linux.

Я писал о rsync здесь, в теме о scp:
Как оптимально скопировать большое количество небольших файлов через scp?

Rsync описан там в записи от JohnU.

Я столкнулся с той же проблемой и нашел это обсуждение при поиске с сообщением об ошибке, используя Ubuntu 24.04 на исходной машине и Ubuntu 24.10 на целевой. Я добавил строку EXPORT в начало файла .bashrc, поэтому сделал то же самое, что и mtvec: переместил строки

# Если не интерактивный режим, ничего не делать 
[ -z "$PS1" ] && return

затем сделал source файла .bashrc, повторил попытку, и это сработало!

.

Ответ или решение

Когда SCP завершается без видимой ошибки и не осуществляет копирование файлов, это может быть весьма озадачивающим, особенно если средство не указывает явной причины. Распечатка множества символов подчёркивания, как указано в примере, может служить ключом к пониманию проблемы. Даная ситуация может возникнуть, если в конфигурационные файлы оболочки, такие как .bashrc или bash.bashrc, включены команды, производящие вывод на экран. Давайте детально разберёмся в этом вопросе и выясним, как его можно решить.

Теория

ssh и scp взаимодействуют через текстовые потоки, ожидая обмен сообщениями между клиентом и сервером в определённом формате, заранее не предполагающем нестандартный вывод. Если какой-либо вывод появляется прежде, чем форматы данных SCP, это может вызвать сбой. Важной частью этой проблемы является форма команд, например, fortune | cowsay, которые дают текстовый вывод при запуске оболочки.

SCP запускает удалённую оболочку для выполнения команд, и если в этих оболочках присутствует нестандартный вывод (кроме ожидаемых форматов), это нарушает работу SCP. Также поведение может быть вызвано изменениями как в локальных, так и в глобальных конфигурационных файлах Bash, как в .bashrc в домашнем каталоге пользователя, так и в системных файлах, таких как /etc/bash.bashrc.

Пример

Многие пользователи могут не осознавать, что вывод, порождаемый их .bashrc, может негативно влиять на работу SCP. Рассмотрим пример: пользователь добавляет строку fortune | cowsay в начало своего .bashrc. Эта команда выполняется всякий раз, когда открывается сессия и порождает текстовый вывод в виде ASCII-арт. В интерактивных сессиях такая надстройка может быть безвредной и даже развлекательной, но в случае SCP такой вывод не допускается.

Применение

Для предотвращения подобных проблем необходимо изменить .bashrc с учетом совместимости неинтерактивных сессий.

  1. Проверьте содержимое вашего .bashrc на наличие команд, которые могут давать непосредственный вывод. Такие команды, как echo, не должны запускаться по умолчанию.

  2. В начало файла .bashrc добавьте оболочный условный оператор, который прекратит выполнение при неинтерактивной сессии:

    # Если не в интерактивной сессии, не делать ничего
    [[ $- != *i* ]] && return
  3. При наличии аналогичных проблем в глобальном /etc/bash.bashrc убедитесь, что в нём так же установлены условия для избежания вывода в неинтерактивных сессиях.

  4. Для достижения наибольшей безопасности можно использовать специальные опции SCP, такие как -o RequestTTY=no, что предотвращает запрос терминала, минимизируя риск нежелательного вывода работы, например:

    scp -o RequestTTY=no <source> <destination>
  5. Рассмотрите возможность использования более надежных инструментов, таких как rsync, которые лучше адаптированы к копированию данных и могут игнорировать посторонний вывод.

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

Оцените материал
Добавить комментарий

Капча загружается...