Usa .bashrc senza interrompere sftp


20

Il mio problema è che devo impostare alcune variabili e generare alcune righe ogni volta che accedo alla shell ssh, e allo stesso tempo devo essere in grado di usare sftp per trasmettere file via Filezilla.

Ora, secondo le FAQ di openssh su http://www.openssh.org/faq.html , se i tuoi script di avvio fanno eco a qualsiasi tipo di output, si incasina con sftp. Quindi, o ritarda indefinitamente o errori con una "Connessione chiusa dal server con codice di uscita 128".

Ho provato soluzioni come spostare .bashrc in .bash_profile o usare il seguente codice in .bashrc:

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

E:

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

Tuttavia, nulla funziona. Il mio terminale shell è bash e mi collego a sftp con filezilla.

Risposte:


23

Prova invece a farlo

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

17

La risposta di Mike probabilmente funzionerà. Ma vale la pena sottolineare che è possibile eseguire questa operazione selezionando accuratamente i file di avvio in cui inserire le informazioni dettagliate. Dalla pagina man di bash:

Quando bash viene invocato come shell di login interattiva o come shell non interattiva con l'opzione --login, legge prima ed esegue i comandi dal file / etc / profile, se quel file esiste. Dopo aver letto quel file, cerca ~ / .bash_profile, ~ / .bash_login e ~ / .profile, in quell'ordine, e legge ed esegue i comandi dal primo che esiste ed è leggibile. L'opzione --noprofile può essere usata all'avvio della shell per inibire questo comportamento.

Quando viene avviata una shell interattiva che non è una shell di accesso, bash legge ed esegue i comandi da ~ / .bashrc, se quel file esiste. Questo può essere inibito usando l'opzione --norc. L'opzione --rcfile forzerà bash a leggere ed eseguire comandi dal file anziché ~ / .bashrc.

Gli strumenti sftp / scp avviano una shell interattiva non di accesso, quindi .bashrc verrà fornito. Molte distribuzioni provengono da .bashrc da .bash_profile o viceversa, quindi può creare confusione. Un buon trucco per testare la pulizia del tuo ambiente di login è ssh in con un comando, che simula allo stesso modo scp / sftp connect. Ad esempio: ssh myhost /bin/trueti mostrerà esattamente cosa vede scp / sftp quando si connettono.

Una semplice 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$

Il primo test provocherà l'interruzione di scp / sftp / rsync ecc. La seconda versione funzionerà bene.


Non sono d'accordo sul fatto che "Gli strumenti sftp / scp avviano una shell interattiva senza accesso" poiché non possiamo realmente interagire con la shell. Ma non capisco perché .bashrcdovrebbe essere ricercato per scpo ssh host command.
pynexj,

2
Il termine "interattivo" non è soggettivo. È un termine usato da bash per descrivere una delle sue modalità di avvio. È un dato di fatto che sftp / scp avvia una "shell interattiva non di accesso". Sentiti libero di discutere con gli sviluppatori sull'opportunità di non approvare .bashrc in questo caso; Ti sto solo dicendo cosa fa.
Insyte,

2
Bashinvocato da scpo ssh host commandè effettivamente non interattivo . Ho appena trovato questo nel manuale di bash: "Bash tenta di determinare quando viene eseguito con il suo input standard collegato a una connessione di rete , come quando eseguito dal daemon di shell remoto, di solito rshd, o dal daemon di shell sicuro sshd . Se bash determina viene eseguito in questo modo, legge ed esegue i comandi da ~/.bashrc, se quel file esiste ed è leggibile. " Ecco la storia interessante .
pynexj,

1
Vedi anche la sezione Shell remote non interattive non login in questa pagina wiki .
pynexj,

3

Se stai usando csh:

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

E se è bash:

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

o in alternativa usando espressioni regolari bash:

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

Queste linee dovrebbero precedere le linee in cui si espande / riecheggia qualcosa.


Ciao, potresti spiegare il codice, per favore. Lo so che $? è il livello di ritorno del comando precedente. Non capisco $? Prompt e $ -, comunque. O è csh specifico?
Joel G Mathew

1
@Droidzone: $?varin cshresi 1 se varè definito e 0 altrimenti. $-in bashavrebbe il icarattere nel suo valore se la shell è interattiva.
pynexj,

Dovrebbe aggiornare la risposta per spiegare $ - è una variabile speciale di opzioni di shell. vedi stackoverflow.com/questions/5163144/...
maninvan

1

La soluzione di Mike ha funzionato anche per me. Ma poiché la mia shell predefinita è TCSH, ho dovuto modificare leggermente la correzione come segue (in .tcshrc):

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

Ho solo pensato di condividere a beneficio di tutti.


0

Mi piacciono alcune delle altre soluzioni menzionate qui meglio, ma ho pensato di buttare via la soluzione che attualmente uso sulle mie macchine virtuali bash e csh per prevenire le disconnessioni SFTP a causa di comandi echo nei miei script di avvio, nel caso in cui qualcuno trovi utili le informazioni .

In 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

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

È un po 'bruta, ma funziona.


Ho provato a utilizzare il codice ["$ SSH_TTY"] sopra e ho scoperto che funzionava solo con programmi client semplici come putty. Quando uso NoMachine non fornisce alcun output. Questo è il motivo per cui ho dovuto includere "xterm-256color" nel codice sopra.
Bob Noonan,

È interessante notare che anche l'uso di "if ($? SSH_TTY) then" non ha funzionato per la mia VM csh. Ho controllato e non è stata definita alcuna variabile di ambiente SSH_TTY. Quindi il mio codice sopra può essere utile per gli altri che hanno una situazione simile.
Bob Noonan,

0

Ecco le prime righe del mio .bashrcfile (predefinito) :

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

Il controllo per una sessione interattiva evita di incasinare SCP, SFTP o la ssh remote-host commandmodalità.

Senza questo, se il tuo file .bashrcutilizza echoo altre cose che stampano su stdout, potresti ricevere questo tipo di errori:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.