SCP не працює, коли лунає в .bashrc?


81

У мене два користувачі у Fedora:

  1. Вані
  2. root (цілком очевидно!)

Мій вміст .bashrc користувача Wani:

# .bashrc
echo "Hello"
# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

# User specific aliases and functions

Тепер після входу в root я ввожу такі команди:

[root@Dell Wani]# touch try.txt
[root@Dell Wani]# service sshd start
[root@Dell Wani]# scp try.txt Wani@localhost:~/
Wani@localhost's password: 
Hello
[root@Dell Wani]# 

Тепер я заходжу в Wani і набираю:

[Wani@Dell ~]$ cat try.txt
cat: try.txt: No such file or directory
[Wani@Dell ~]$ 

Тепер я знову заходжу в root і набираю ту саму команду за допомогою -v:

[root@Dell Wani]# scp -v morph.log Wani@localhost:
Executing: program /usr/bin/ssh host localhost, user Wani, command scp -v -t -- .
OpenSSH_5.6p1, OpenSSL 1.0.0j-fips 10 May 2012
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to localhost [127.0.0.1] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/id_rsa type -1
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.6
debug1: match: OpenSSH_5.6 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.6
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: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host 'localhost' is known and matches the RSA host key.
debug1: Found key in /root/.ssh/known_hosts:2
debug1: ssh_rsa_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,gssapi-keyex,gssapi-     with-mic,password
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Next authentication method: publickey
debug1: Trying private key: /root/.ssh/id_rsa
debug1: Trying private key: /root/.ssh/id_dsa
debug1: Next authentication method: password
Wani@localhost's password: 
debug1: Authentication succeeded (password).
Authenticated to localhost ([127.0.0.1]:22).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env XMODIFIERS = @im=none
debug1: Sending env LANG = en_US.UTF-8
debug1: Sending command: scp -v -t -- .
Hello
[root@Dell Wani]# 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 1664, received 1976 bytes, in 0.1 seconds
Bytes per second: sent 22961.5, received 27266.8
debug1: Exit status 0

(І після того, як я натиснув Enter)

[root@Dell Wani]# 

Хтось може пролити світло, що саме тут сталося? Чому файл не скопійовано в Wani з root?


Що про cp? Працює cp try.txt ~Wani/?
nneonneo

Дійсно, можливо, що інтерактивні команди або хибні результати з вашого .bashrcможуть зіпсувати деякі неінтерактивні сценарії. Спробуйте зробити код обумовленим case $- in *i*або деяким подібним.
триплеє

@nneonneo: Це працює. Насправді, навіть якщо у мене двоє користувачів на різних комп’ютерах, файл не копіюється!
Nehal J Wani,

1
Усі повідомлення, які я бачив, описують ЧОМУ ця проблема існує у різних файлах bashrc тощо. Однак, коли SCP / STFP на машині ви НЕ ВЛАСНІ і НЕ МОЖЕТЕ змінити сценарії запуску, яке рішення тоді?
ChuckB

У підсумку я перенаправив усі відлуння на stderr. Працює, але ...
Андреас

Відповіді:


78

Використання echoу .bashrcволі зламається scp, оскільки scpочікується побачити дані протоколу по каналах stdin / stdout. Докладніше про це дивіться на https://bugzilla.redhat.com/show_bug.cgi?id=20527 .

Доступно кілька обхідних шляхів:

  • Умова на case $- in *i*позначці "інтерактив" (наприклад, як запропонував тріплі)
  • Використовуйте ttyпрограму для виявлення інтерактивної оболонки (наприклад, if tty > /dev/nullабо if [ -t 0 ])
  • Перевірте значення $SSH_TTY

Думаю, вам слід використовувати той, який вам підходить. Я не знаю, який найкращий (найбільш портативний / найнадійніший) варіант, на жаль.


6
Просто для роз'яснення команди "case" буде:case $- in *i*) echo This is safe since the shell is interactive; esac
mlathe

shoptтакож є альтернативою
весперто

1
Оскільки мій хост завжди доступний через SSH, SSH_TTY завжди встановлений. Використання -t 0умови мені добре вдалось. Зараз я використовую наступну функцію по всьому моєму bashrc. safe_echo() { if [[ -t 0 ]];then echo -e "$*" fi }
Сандіп Бхаттачарія,

if [[ "$SSH_TTY" == */dev/pts/* ]] ; thenвсередині, якщо розмістити вміст, який друкується в stdout, тоді scp буде працювати нормально.
BeatingBytes

@BeatingBytes & @Sandip Bhattacharya, [[не є портативним, і я також не думаю, що це posix. Спробуйте це в dashоболонці: if [[ 0 = 0 ]]; then echo x; else echo y; fi. Ви отримуєте, dash: 3: [[: not found.
Еліптичний вигляд

19

Щоб додати параметри nneonneo, ви також можете обумовити інтерактивний прапор з

if [[ $- =~ "i" ]]

що, на мою думку, є, мабуть, найбільш зрозумілим способом в bash.


[[не є портативним, і я також не думаю, що це posix. Спробуйте це в dashоболонці: if [[ 0 = 0 ]]; then echo x; else echo y; fi. Ви отримуєте, dash: 3: [[: not found.
Еліптичний вигляд


11

За замовчуванням Ubuntu .bashrcмістить наступний фрагмент коду , який вже піклується про проблему:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac

4
коротше:[[ $- != *i* ]] && return
phil294

2
Форма, надана у вашій відповіді, сумісна з POSIX. Те, що ви пропонуєте у своєму коментарі, не є POSIX через використання [[функції. Не так проблематично для файлу bashrc;), але, можливо, ви захочете мати можливість використовувати його в іншому контексті / оболонці.
Тотор,

4

Замість цього .bashrcвикористовуйте STDERR як вихід:

echo "# Important Notice" >&2

Оновлення: не використовуйте його! Нещодавно у нас виникла проблема з тим, що засіб (із закритим кодом) вийшов з ладу через echoSTDERR у .bashrc. Інструмент (використовуючи rcp) не очікував вихідних даних взагалі, ні на STDOUT, ні на STDERR. І вона застрягла, коли отримала відгомін. Вивчений урок: робіть окремі рахунки для людей та для машин (сценарії), або просто припиніть мовчати через .bashrc.


"Зробити окремі рахунки для людей і машин" недооцінено.
Андреас,

1

Найбільш портативним способом тестування інтерактивної оболонки є:

test -t 0
if [ $? -eq 0 ]
then
    # interactive
    ;
else
    # non-interactive
    ;
fi

0

Рішення nneonneo спрацювало і на мене. Але оскільки моєю оболонкою за замовчуванням є TCSH, мені довелося трохи відредагувати виправлення наступним чином (у .tcshrc):

if ( $?SSH_TTY ) then
    exec /bin/bash
endif

Просто думав, що поділюсь для всіх.


0

Якщо ви використовуєте Red Hat Enterprise Linux (RHEL) або його варіант, опустіть скрипт, який виконує echoабо що завгодно, у /etc/profile.d/


0

Якщо ви також хочете ехо-висловлювання, у відповіді @ Blauhirn, ви можете продовжувати розміщувати свої ехо-висловлювання після умови справи.

case $- in
    *i*) ;;
    *) return;;
esac

echo "Your Greeting/Warning Message/s here!"

-1
if [ 0 -eq $(shopt -q login_shell; echo $?) ]; then
  echo "do something?"
fi

Джерело


Було б непогано надати певний контекст для ОП.
aljabear

Контекст та відповідну інформацію вже можна отримати з інших відповідей та самого питання. Це лише ще один спосіб зробити те, що вже зрозуміло, з низьким співвідношенням сигнал / шум.
весперто
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.