Use .bashrc sem quebrar o sftp

20

Meu problema é que preciso definir algumas variáveis ​​e gerar algumas linhas toda vez que faço login no shell ssh, e ao mesmo tempo tenho que poder usar o sftp para tarnsferir arquivos via Filezilla.

Agora, de acordo com a FAQ do openssh em http://www.openssh.org/faq.html , se seus scripts de inicialização ecoarem qualquer tipo de saída, ele estragará o sftp. Por isso, atrasa indefinidamente ou sai com um erro "Conexão fechada pelo servidor com o código de saída 128".

Tentei soluções como mover .bashrc para .bash_profile ou usar o seguinte código em .bashrc:

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

E:

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

No entanto, nada funciona. Meu terminal shell é bash e eu me conecto ao sftp com o filezilla.

Joel G Mathew
fonte

Respostas:

23

Tente fazer isso

if [ "$SSH_TTY" ]
then
   source .bashc_real
fi
Mike
fonte
17

A resposta de Mike provavelmente funcionará. Mas vale ressaltar que você pode realizar isso cuidadosamente selecionando quais arquivos de inicialização colocar os itens detalhados. Na página de manual do bash:

Quando o bash é chamado como um shell de login interativo ou como um shell não interativo com a opção --login, ele primeiro lê e executa comandos do arquivo / etc / profile, se esse arquivo existir. Depois de ler esse arquivo, ele procura ~ / .bash_profile, ~ / .bash_login e ~ / .profile, nessa ordem, e lê e executa comandos do primeiro que existe e é legível. A opção --noprofile pode ser usada quando o shell é iniciado para inibir esse comportamento.

Quando um shell interativo que não é um shell de login é iniciado, o bash lê e executa comandos de ~ / .bashrc, se esse arquivo existir. Isso pode ser inibido usando a opção --norc. A opção --rcfile file forçará o bash a ler e executar comandos do arquivo em vez de ~ / .bashrc.

As ferramentas sftp / scp iniciam um shell interativo sem logon, portanto, o .bashrc será originado. Muitas distribuições usam o .bashrc como .bash_profile ou vice-versa, para que fique confuso. Um bom truque para testar a limpeza do seu ambiente de login é fazer o ssh com um comando, que simula da mesma maneira que o scp / sftp connect. Por exemplo: ssh myhost /bin/truemostrará exatamente o que o scp / sftp vê quando eles se conectam.

Uma demonstração simples:

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$

O primeiro teste fará com que scp / sftp / rsync etc. quebre. A segunda versão funcionará bem.

Insyte
fonte
Eu não concordo que "As ferramentas sftp / scp iniciam um shell interativo sem logon", pois não podemos realmente interagir com o shell. Mas eu não entendo por .bashrcque seria fonte para scpou ssh host command.
pynexj
2
O termo "interativo" não é subjetivo. É um termo usado pelo bash para descrever um de seus modos de inicialização. É fato que o sftp / scp inicia um "shell interativo de não login". Sinta-se à vontade para discutir com os desenvolvedores se o sourcing .bashrc não é apropriado nesse caso; Só estou lhe dizendo o que faz.
Insyte 26/03
2
Bashinvocado por scpou ssh host commandé realmente não interativo . Acabei de encontrar isso no manual do bash: "O Bash tenta determinar quando está sendo executado com sua entrada padrão conectada a uma conexão de rede , como quando executada pelo daemon de shell remoto, geralmente rshd, ou pelo daemon de shell seguro sshd . Se o bash determinar está sendo executado dessa maneira, lê e executa comandos de ~/.bashrc, se esse arquivo existir e for legível. " Aqui está a história interessante .
pynexj
1
Veja também a seção conchas remoto não de login não interativos em esta página wiki .
pynexj
3

Se você estiver usando o csh:

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

E se é bash:

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

ou, alternativamente, usando expressões regulares do bash:

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

Essas linhas devem preceder as linhas nas quais você reproduz / reproduz algo de volta.

user163384
fonte
Oi, você poderia explicar o código, por favor. Eu sei que $? é o nível de retorno do comando anterior. Eu não entendo $? Prompt e $ -, no entanto. Ou o csh é específico?
Joel G Mathew
1
@Droidzone: $?varin cshretorna 1 se varfor definido e 0 caso contrário. $-in bashteria o ichar em seu valor se o shell for interativo.
pynexj
Deve atualizar a resposta para explicar $ - é uma variável especial das opções do shell. Veja stackoverflow.com/questions/5163144/…
maninvan
1

A solução de Mike também funcionou para mim. Mas como meu shell padrão é TCSH, tive que editar levemente a correção da seguinte maneira (em .tcshrc):

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

Apenas pensei em compartilhar para o benefício de todos.

Vijay Padiyar
fonte
0

Eu gosto mais de outras soluções mencionadas aqui, mas pensei em lançar a solução que atualmente uso em minhas VMs bash e csh para evitar desconexões de SFTP devido a comandos de eco nos meus scripts de inicialização, apenas caso alguém ache as informações úteis .

No 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

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

É um pouco de força bruta, mas funciona.

Bob Noonan
fonte
Tentei usar o código ["$ SSH_TTY"] acima e descobri que ele só funcionava para programas clientes simples como o putty. Quando uso o NoMachine, ele não fornece nenhuma saída. É por isso que eu precisei incluir "xterm-256color" no código acima.
Bob Noonan
Curiosamente, o uso de "if ($? SSH_TTY) then" também não funcionou para minha VM csh. Eu verifiquei e não há nenhuma variável de ambiente SSH_TTY definida. Portanto, meu código acima pode ser útil para outras pessoas que têm uma situação semelhante.
Bob Noonan
0

Aqui estão as primeiras linhas do meu .bashrcarquivo (padrão) :

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

A verificação de uma sessão interativa evita a bagunça com SCP, SFTP ou ssh remote-host commandmodo.

Sem isso, se o seu arquivo .bashrcusar echoou imprimir outras coisas no stdout, você poderá obter este tipo de erro:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Totor
fonte