Use .bashrc sin romper sftp


20

Mi problema es que necesito establecer algunas variables y generar algunas líneas cada vez que inicio sesión en el shell ssh, y al mismo tiempo tengo que poder usar sftp para transferir archivos a través de Filezilla.

Ahora, según las preguntas frecuentes de openssh en http://www.openssh.org/faq.html , si sus scripts de inicio hacen eco de algún tipo de salida, se estropea con sftp. Por lo tanto, se retrasa indefinidamente o se produce un error con una "Conexión cerrada por el servidor con el código de salida 128".

He intentado soluciones como mover .bashrc a .bash_profile, o usar el siguiente código en .bashrc:

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

Y:

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

Sin embargo, nada funciona. Mi terminal de shell es bash, y me conecto a sftp con filezilla.

Respuestas:


23

Intenta hacer esto en su lugar

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

17

La respuesta de Mike probablemente funcionará. Pero vale la pena señalar que puede lograr esto cuidadosamente seleccionando en qué archivos de inicio colocar las cosas detalladas. Desde la página de manual de bash:

Cuando se invoca bash como un shell de inicio de sesión interactivo o como un shell no interactivo con la opción --login, primero lee y ejecuta comandos del archivo / etc / profile, si ese archivo existe. Después de leer ese archivo, busca ~ / .bash_profile, ~ / .bash_login y ~ / .profile, en ese orden, y lee y ejecuta comandos del primero que existe y es legible. La opción --noprofile se puede usar cuando se inicia el shell para inhibir este comportamiento.

Cuando se inicia un shell interactivo que no es un shell de inicio de sesión, bash lee y ejecuta comandos desde ~ / .bashrc, si ese archivo existe. Esto puede inhibirse usando la opción --norc. La opción de archivo --rcfile obligará a bash a leer y ejecutar comandos desde el archivo en lugar de ~ / .bashrc.

Las herramientas sftp / scp inician un shell interactivo sin inicio de sesión, por lo que se obtendrá .bashrc. Muchas distribuciones obtienen .bashrc de .bash_profile o viceversa, por lo que puede resultar confuso. Un buen truco para probar la limpieza de su entorno de inicio de sesión es ssh con un comando, que simula la misma forma en que se conecta scp / sftp. Por ejemplo: ssh myhost /bin/truele mostrará exactamente lo que scp / sftp ve cuando se conectan.

Una demostración simple:

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$

La primera prueba hará que scp / sftp / rsync, etc. se rompa. La segunda versión funcionará bien.


No estoy de acuerdo con que "Las herramientas sftp / scp inician un shell interactivo sin inicio de sesión" ya que no podemos interactuar realmente con el shell. Pero no entiendo por qué .bashrcsería fuente de scpo ssh host command.
pynexj

2
El término "interactivo" no es subjetivo. Es un término utilizado por bash para describir uno de sus modos de inicio. Es un hecho que sftp / scp inicia un "shell interactivo sin inicio de sesión". Siéntase libre de discutir con los desarrolladores sobre si no es apropiado obtener .bashrc en este caso; Solo te digo lo que hace.
Insyte

2
Bashinvocado por scpo ssh host commandes de hecho no interactivo . Acabo de encontrar esto en el manual de bash: "Bash intenta determinar cuándo se está ejecutando con su entrada estándar conectada a una conexión de red , como cuando lo ejecuta el demonio de shell remoto, generalmente rshd, o el demonio de shell seguro sshd . Si bash determina se ejecuta de esta manera, lee y ejecuta comandos desde ~/.bashrc, si ese archivo existe y es legible ". Aquí está la historia interesante .
pynexj

1
Consulte también la sección Shells remotos no interactivos sin inicio de sesión en esta página wiki .
pynexj

3

Si estás usando csh:

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

Y si es bash:

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

o alternativamente usando bash expresiones regulares:

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

Estas líneas deben preceder a las líneas en las que sale / repite algo.


Hola, ¿podrías explicar el código, por favor? Sé que $? es el nivel de retorno del comando anterior. Sin embargo, no entiendo $? Prompt y $ -. ¿O es csh específico?
Joel G Mathew

1
@Droidzone: $?varen cshdevuelve 1 si varestá definido y 0 en caso contrario. $-in bashtendría el ivalor de char en su valor si el shell es interactivo.
pynexj

Debería actualizar la respuesta para explicar $ - es una variable especial de opciones de shell. ver stackoverflow.com/questions/5163144/…
maninvan el

1

La solución de Mike también funcionó para mí. Pero dado que mi shell predeterminado es TCSH, tuve que editar ligeramente la corrección de la siguiente manera (en .tcshrc):

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

Solo pensé en compartir para beneficio de todos.


0

Me gustan algunas de las otras soluciones mencionadas aquí mejor, pero pensé que descartaría la solución que actualmente uso en mis máquinas virtuales bash y csh para evitar desconexiones SFTP debido a comandos de eco en mis scripts de inicio, en caso de que alguien encuentre útil la información .

En 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

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

Es un poco fuerza bruta, pero funciona.


Intenté usar el código ["$ SSH_TTY"] anterior y descubrí que solo funcionaba para programas cliente simples como masilla. Cuando uso NoMachine no proporciona ningún resultado. Es por eso que necesitaba incluir "xterm-256color" en el código anterior.
Bob Noonan

Curiosamente, usar "if ($? SSH_TTY) then" tampoco funcionó para mi máquina virtual csh. Lo comprobé y no hay una variable de entorno SSH_TTY definida. Por lo tanto, mi código anterior puede ser útil para otras personas que tienen una situación similar.
Bob Noonan

0

Aquí están las primeras líneas de mi .bashrcarchivo (predeterminado) :

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

La comprobación de una sesión interactiva evita la confusión con SCP, SFTP o ssh remote-host commandmodo.

Sin esto, si su archivo .bashrcusa echou otras cosas que se imprimen en stdout, puede obtener este tipo de errores:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.