Użyj .bashrc bez przerywania sftp

20

Mój problem polega na tym, że muszę ustawić kilka zmiennych i wypisywać kilka wierszy za każdym razem, gdy loguję się do powłoki ssh, a jednocześnie muszę mieć możliwość używania sftp do tarnsferowania plików za pomocą Filezilli.

Teraz, zgodnie z FAQ openssh na http://www.openssh.org/faq.html , jeśli twoje skrypty startowe odbijają jakiekolwiek wyniki, to miesza się z sftp. Opóźnia się więc w nieskończoność lub kończy się błędem „Połączenie zamknięte przez serwer z kodem wyjścia 128”.

Wypróbowałem rozwiązania takie jak przeniesienie .bashrc do .bash_profile lub użycie następującego kodu w .bashrc:

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

I:

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

Jednak nic nie działa. Mój terminal powłoki to bash i łączę się z sftp za pomocą filezilli.

Joel G. Mathew
źródło

Odpowiedzi:

23

Spróbuj to zrobić zamiast tego

if [ "$SSH_TTY" ]
then
   source .bashc_real
fi
Mikrofon
źródło
17

Odpowiedź Mike'a prawdopodobnie zadziała. Warto jednak zaznaczyć, że można to dokładnie zrobić, wybierając pliki startowe, w których można umieścić pełne informacje. Ze strony podręcznika użytkownika bash:

Kiedy bash jest wywoływany jako interaktywna powłoka logowania lub jako nieinteraktywna powłoka z opcją --login, najpierw czyta i wykonuje polecenia z pliku / etc / profile, jeśli plik ten istnieje. Po odczytaniu tego pliku szuka ~ / .bash_profile, ~ / .bash_login i ~ / .profile, w tej kolejności, i odczytuje i wykonuje polecenia z pierwszego, który istnieje i jest czytelny. Opcji --noprofile można użyć, gdy powłoka zostanie uruchomiona w celu zahamowania tego zachowania.

Po uruchomieniu interaktywnej powłoki, która nie jest powłoką logowania, bash czyta i wykonuje polecenia z ~ / .bashrc, jeśli plik istnieje. Można temu zapobiec, używając opcji --norc. Opcja pliku --rcfile zmusi bash do odczytu i wykonywania poleceń z pliku zamiast ~ / .bashrc.

Narzędzia sftp / scp uruchamiają interaktywną powłokę niezalogowaną, więc źródłowy będzie .bashrc. Wiele dystrybucji pobiera .bashrc z .bash_profile lub odwrotnie, więc może to być mylące. Dobrą sztuczką do testowania czystości środowiska logowania jest ssh in z poleceniem, które symuluje w ten sam sposób połączenie scp / sftp. Na przykład: ssh myhost /bin/truepokaże ci dokładnie to, co widzi scp / sftp podczas łączenia.

Proste demo:

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$

Pierwszy test spowoduje uszkodzenie scp / sftp / rsync itp. Druga wersja będzie działać dobrze.

Insyte
źródło
Nie zgadzam się, że „Narzędzia sftp / scp uruchamiają interaktywną powłokę niezalogowaną”, ponieważ tak naprawdę nie możemy wchodzić w interakcje z powłoką. Ale nie rozumiem, dlaczego .bashrcmiałoby być źródłem dla scplub ssh host command.
pynexj
2
Termin „interaktywny” nie jest subiektywny. Jest to termin używany przez bash do opisania jednego z trybów uruchamiania. Faktem jest, że sftp / scp uruchamia „interaktywną powłokę bez logowania”. Nie krępuj się spierać z programistami, czy w takim przypadku nie jest konieczne pozyskiwanie .bashrc; Po prostu mówię ci, co robi.
Insyte
2
Bashwywoływane przez scplub ssh host commandfaktycznie jest nieinteraktywne . Właśnie znalazłem to w podręczniku bash: „Bash próbuje ustalić, kiedy jest uruchamiany ze standardowym wejściem podłączonym do połączenia sieciowego , tak jak w przypadku wykonania przez zdalnego demona powłoki, zwykle rshd, lub bezpiecznego demona powłoki sshd . Jeśli bash określa jest uruchamiany w ten sposób, odczytuje i wykonuje polecenia z ~/.bashrc, jeśli ten plik istnieje i jest możliwy do odczytu. ” Oto interesująca historia .
pynexj
1
Zobacz także sekcję Zdalne non-login nieinteraktywne powłoki na tej stronie wiki .
pynexj
3

Jeśli używasz csh:

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

A jeśli to bash:

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

lub alternatywnie używając wyrażeń regularnych bash:

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

Te wiersze powinny poprzedzać wiersze, w których wypisujesz / echo coś z powrotem.

użytkownik163384
źródło
Cześć, mógłbyś wyjaśnić kod? Znam to $? jest poziomem powrotu poprzedniego polecenia. Nie rozumiem jednak znaku zachęty $? I $ -. A może csh jest specyficzny?
Joel G.Mathew
1
@Droidzone: $?varw cshzwraca 1 jeśli varjest zdefiniowane, a 0 w przeciwnym razie. $-in bashma ichar w swojej wartości, jeśli powłoka jest interaktywna.
pynexj
Powinny zaktualizować odpowiedź, aby wyjaśnić $ - jest specjalną zmienną opcji powłoki. patrz stackoverflow.com/questions/5163144/…
maninvan,
1

Rozwiązanie Mike'a również zadziałało dla mnie. Ale ponieważ moją domyślną powłoką jest TCSH, musiałem nieznacznie edytować poprawkę w następujący sposób (w .tcshrc):

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

Pomyślałem, że podzielę się z korzyścią dla wszystkich.

Vijay Padiyar
źródło
0

Bardziej podoba mi się niektóre inne wymienione tutaj rozwiązania, ale pomyślałem, że wyrzucam rozwiązanie, którego obecnie używam na maszynach wirtualnych bash i csh, aby zapobiec rozłączaniu się SFTP z powodu poleceń echa w moich skryptach startowych, na wypadek, gdyby ktoś uznał te informacje za pomocne .

W BASH:

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

W 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"

To trochę brutalna siła, ale działa.

Bob Noonan
źródło
Próbowałem użyć powyższego kodu [„$ SSH_TTY”] i stwierdziłem, że działa on tylko w przypadku prostych programów klienckich, takich jak putty. Gdy korzystam z NoMachine, nie zapewnia on żadnych danych wyjściowych. Właśnie dlatego musiałem dołączyć „xterm-256color” do powyższego kodu.
Bob Noonan
Co ciekawe, użycie „if ($? SSH_TTY) następnie” również nie działało na mojej maszynie wirtualnej csh. Sprawdziłem i nie ma zdefiniowanej zmiennej środowiskowej SSH_TTY. Więc mój powyższy kod może być pomocny dla innych, którzy mają podobną sytuację.
Bob Noonan
0

Oto pierwsze wiersze mojego (domyślnego) .bashrcpliku:

# ~/.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

Sprawdzenie sesji interaktywnej pozwala uniknąć bałaganu w SCP, SFTP lub ssh remote-host commandtrybie.

Bez tego, jeśli twój plik .bashrcużywa echolub jakieś inne rzeczy drukują na standardowym ekranie, możesz otrzymać tego rodzaju błędy:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Totor
źródło