Використовуйте .bashrc, не порушуючи sftp


20

Моя проблема полягає в тому, що мені потрібно встановити кілька змінних і вивести кілька рядків щоразу, коли я входжу в оболонку ssh, і в той же час мені потрібно мати можливість використовувати sftp для файлів tarnsfer через Filezilla.

Тепер, відповідно до відкритого FAQ на веб- сайті http://www.openssh.org/faq.html , якщо ваші сценарії запуску повторюються з будь-яким результатом, він заплутається з sftp. Таким чином, або затримується на невизначений термін, або помилки з "З'єднанням, закритим сервером, з кодом виходу 128".

Я спробував такі рішення, як переміщення .bashrc до .bash_profile або використання наступного коду в .bashrc:

if [ "$TERM" != "dumb" ]
then
   source .bashc_real
fi

І:

if [ "$TERM" = "xterm" ]
then
   source .bashc_real
fi

Однак нічого не працює. Мій термінал оболонки - bash, і я з'єднуюся з sftp за допомогою filezilla.

Відповіді:


23

Спробуйте зробити це замість цього

if [ "$SSH_TTY" ]
then
   source .bashc_real
fi

17

Відповідь Майка, ймовірно, спрацює. Але варто зазначити, що ви можете це ретельно вибирати, які файли запуску для розміщення багатослівних речей. З сторінки bash man:

Коли bash викликається як інтерактивна оболонка входу, або як неінтерактивна оболонка з опцією --login, вона спочатку зчитує та виконує команди з файлу / etc / profile, якщо такий файл існує. Прочитавши цей файл, він шукає у такому порядку ~ / .bash_profile, ~ / .bash_login та ~ / .profile та зчитує та виконує команди з першого, який існує та читається. Параметр --noprofile може використовуватися, коли оболонка запускається для пригнічення такої поведінки.

Коли запускається інтерактивна оболонка, яка не є оболонкою для входу, bash зчитує та виконує команди з ~ / .bashrc, якщо цей файл існує. Це може бути пригнічено за допомогою параметра --norc. Параметр файлу --rcfile змусить bash читати та виконувати команди з файлу замість ~ / .bashrc.

Інструменти sftp / scp запускають інтерактивну оболонку без входу, тому .bashrc буде отриманий. Багато дистрибутивів джерело .bashrc з .bash_profile або навпаки, так що це може заплутатись. Хороший трюк для перевірки чистоти вашого середовища для входу в систему - ввімкнути команду, яка імітує той самий спосіб підключення scp / sftp. Наприклад: ssh myhost /bin/trueпокаже вам саме те, що бачить scp / sftp, коли вони підключаються.

Проста демонстрація:

insyte@mazer:~$ echo "echo Hello from .profile" > .profile
insyte@mazer:~$ echo "echo Hello from .bashrc" > .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
Hello from .bashrc
sazerac:~ insyte$

insyte@mazer:~$ rm .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
sazerac:~ insyte$

Перший тест призведе до розриву scp / sftp / rsync тощо. Друга версія буде працювати чудово.


Я не згоден, що "інструменти sftp / scp запускають інтерактивну оболонку без входу", оскільки ми не можемо реально взаємодіяти з оболонкою. Але я не розумію , чому .bashrcб source'd для scpабо ssh host command.
pynexj

2
Термін "інтерактивний" не є суб'єктивним. Це термін, який використовується bash для опису одного з його режимів запуску. Це факт, що sftp / scp запускає "інтерактивну оболонку без входу". Не соромтеся сперечатися з розробниками щодо того, чи не підходить .bashrc в цьому випадку; Я просто кажу вам, що це робить.
Insyte

2
Bashвикликається scpабо ssh host commandдійсно неінтерактивний . Я щойно знайшов це в посібнику з bash: "Bash намагається визначити, коли він запускається зі своїм стандартним входом, підключеним до мережевого з'єднання , як коли виконується віддаленим демоном оболонки, як правило, rshd, або захищеним демоном захищеної оболонки sshd . Якщо bash визначає він запускається таким чином, він зчитує і виконує команди ~/.bashrc, якщо цей файл існує і читається ". Ось цікава історія .
pynexj

1
Також дивіться розділ Віддалені неінтерактивні оболонки без входу на цій вікі-сторінці .
pynexj

3

Якщо ви використовуєте csh:

if ($?prompt)
  ... interactive stuff ...

І якщо це баш:

if [[ $- == *i* ]]; then
  ... interactive stuff ...
fi

або альтернативно використовуючи bash регулярні вирази:

if [[ $- =~ i ]]; then
  ... interactive stuff ...
fi

Ці рядки повинні передувати рядкам, де ви повертаєте / повторюєте щось назад.


Привіт, ви можете пояснити код, будь ласка. Я знаю, що $? - рівень повернення попередньої команди. Я не розумію $? Prompt і $ -, хоча. Або специфічний csh?
Joel G Mathew

1
@Droidzone: $?varу cshповерненні 1, якщо varвизначено, а 0 - в іншому випадку. $-in bashби має iзнак у значенні, якщо оболонка інтерактивна.
pynexj

Якщо слід оновити відповідь, щоб пояснити $ - це спеціальна змінна параметрів оболонки. см stackoverflow.com/questions/5163144 / ...
maninvan

1

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

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

Просто думав, що поділюсь на благо кожного.


0

Мені подобаються деякі інші рішення, згадані тут, краще, але я подумав, що я викидаю рішення, яке я зараз використовую на своїх VM-файлах bash і csh, щоб запобігти відключенню SFTP через команди ехо в моїх сценаріях запуску, на всякий випадок, якщо хтось знайде інформацію корисною .

В БАШ:

if [ $TERM == "xterm" ] || [ $TERM == "xterm-256color" ]; then
  echo "Xterm display identified: echo enabled"
  echo_disable="0"
else
  echo_disable="1"
fi

# Use the following for all subsequent echo commands
if [ $echo_disable == 0 ]; then
 echo "Safe to display on Xterm"
fi

В csh:

if ($TERM == "xterm") then
  echo "Xterm display identified: echo enabled"
  set echo_disable = "0"
else
  set echo_disable = "1"
endif

# Use the following for all subsequent echo commands
if !( "$echo_disable" ) echo "Safe to display on Xterm"

Це трохи жорстока сила, але це працює.


Я спробував скористатися кодом ["$ SSH_TTY"] і виявив, що він працює лише для простих клієнтських програм, таких як шпаклівка. Коли я використовую NoMachine, він не забезпечує жодного виводу. Ось чому мені потрібно було включити "xterm-256color" у код вище.
Боб Нунан

Цікаво, що використання "if ($? SSH_TTY) then" також "не працювало для моєї csh VM. Я перевірив, і не визначено змінну середовища SSH_TTY. Тому мій код вище може бути корисним для інших, хто має подібну ситуацію.
Боб Нунан

0

Ось перші рядки мого (за замовчуванням) .bashrcфайлу:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

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

Перевірка інтерактивного сеансу дозволяє уникнути псування з SCP, SFTP або ssh remote-host commandрежимом.

Без цього, якщо у вашому файлі .bashrcвикористовується echoдрук або інший матеріал на stdout, ви можете отримати такі помилки:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.