A correção para isso é normalmente simples. Normalmente, você pode inspecionar .bashrc
, localizar a linha ou algumas linhas próximas ao topo que estão causando o problema e movê-las ou excluí-las. A parte difícil é convencer as pessoas de que esse problema é realmente real. Os detalhes seguem, mas se você quiser apenas consertar esse problema, você só precisará usar esta primeira seção mais curta.
O problema e como resolvê-lo
Isso acontece quando .bashrc
no diretório pessoal do usuário na máquina remota contém comandos que produzem saída e que funcionam mesmo em shells não-interativos . Menos comumente, isso também aconteceria se o sistema /etc/bash.bashrc
contivesse tais comandos. O resultado específico varia dependendo do que está produzindo. Mas a combinação de recebimento de saída inesperada e não tendo quaisquer transferências bem sucedidas ou mesmo iniciando muito aponta strongmente para essa causa (especialmente quando o servidor é um sistema Debian ou Ubuntu). scp
usa entrada e saída padrão para enviar e receber dados, e se dados não relacionados forem transmitidos através deles, não poderá ser transferido arquivos.
Se você está pensando, "Isso é impossível, .bashrc
é apenas para shells interativos!" ou caso esteja interessado em uma explicação detalhada do porque isso ocorre, veja a segunda seção abaixo. / p>
Este problema não quebra o SSHing normal. Portanto, supondo que o sistema esteja configurado para permitir que você ssh
com êxito para um shell de login interativo, você pode abrir .bashrc
no diretório inicial do usuário remoto e remover ou comentar (com #
) o comando ou comandos ofensivos, se você não precisar deles. Ou se você precisar deles, mova-os abaixo de outro comando que aborta quando o shell não é interativo. Tal comando pode já estar presente. No Ubuntu, os arquivos .bashrc
dos usuários e /etc/bash.bashrc
geralmente começam com eles.
O arquivo .bashrc
padrão no Ubuntu, copiado de /etc/skel
quando uma conta de usuário é criada, contém este código para verificar se o shell em execução é interativo e para evitar que outros comandos do arquivo sejam executados se ele for < em> não :
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Outro método comum, que algumas pessoas usam em seus arquivos .bashrc
e que atualmente é usado no arquivo /etc/bash.bashrc
em todo o sistema para todos os usuários, é:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Se os arquivos foram substituídos ou modificados do padrão, você poderá ver o uso da técnica em qualquer arquivo. Existem outras maneiras possíveis de verificar a operação interativa, mas elas são incomuns. Se o usuário tiver escrito seu próprio arquivo .bashrc
a partir do zero ou trazido de outro sistema operacional que não seja Debian, Ubuntu ou outro derivado do Debian, é provável que ele não tenha esse código. Mas se você precisar, ainda poderá adicioná-lo.
Qualquer comando que produza saída e apareça em .bashrc
ou /etc/bash.bashrc
, a menos que apareça após código como o mostrado acima, fará com que dados inesperados sejam enviados no início de um scp
session e impedirá que scp
possa transferir arquivos.
Se você mesmo editou recentemente um desses arquivos adicionando um comando ao topo, deve ser fácil descobrir a alteração específica que causou o problema. Mesmo que não, a descrição acima pode lhe dar informações suficientes.
No entanto, eu recomendo que você edite sua pergunta com todos os detalhes, incluindo o conteúdo desses arquivos, mesmo que você não consiga resolver o problema com base na explicação acima. Lembre-se de que estes são os arquivos no servidor remoto, não na máquina cliente . Isso deve ajudar outras pessoas que acham sua pergunta a entender o problema, bem como possibilitar a prestação de conselhos mais específicos, se necessário.
Acredito que a probabilidade do seu problema ser causado por algo completamente diferente seja muito baixo, mas de qualquer forma, a informação adicionada deve tornar possível ter certeza. Outras pessoas que o autor desta questão que têm problemas semelhantes e precisam de ajuda para resolvê-las, obviamente não devem editar essa pergunta, mas devem postar suas próprias perguntas.
Por que o problema ocorre
As pessoas costumam dizer que .bashrc
é apenas para shells interativos, mas isso é um equívoco ou, na melhor das hipóteses, uma simplificação excessiva. bash
executa comandos de ~/.bashrc
e /etc/bash.basrhc
quando :
- o shell é interativo, ou
- outro script de inicialização como
/etc/profile
ou~/.profile
fontes , mas também - quando
bash
está sendo executado não interativamente nem como um shell de login, mas determina que ele provavelmente está sendo executado como o shell inicial em uma conexão remota .
O que bash
toma como evidência suficiente que é um shell remoto - e, portanto, se ou não, na prática, esse efeito ocorre mesmo com o SSH - depende principalmente de como foi compilado, o que varia entre sistemas operacionais e, secundariamente, na versão de bash
e a versão de sshd
que está sendo usada.
Nos sistemas Debian e Ubuntu atuais, quando bash
é executado como um shell não-interativo não-interativo, ele verifica se a variável de ambiente SSH_CLIENT
está definida e não está vazia. (Ele verifica outras coisas também, mas para SSH em sistemas Ubuntu atuais, eles não revelam nada.) Se sim, e a variável de ambiente SHLVL
é definida para um valor menor que 2 - indicando que é a sessão < em> inicial shell - bash
executa os comandos em /etc/bash.bashrc
e ~/.bashrc
.
Para verificar isso rapidamente sem modificar os arquivos de configuração, os leitores podem passar essas variáveis manualmente para o ambiente bash -c ''
e trace o que lê ou examine a função run_startup_files
em shell.c
(que começa na linha 1022 naquela versão).
Um não-login não-interativo bash
shell é o que você obtém quando você executa um script com bash
, seja executando-o após configurar as permissões necessárias e dando a ele uma linha de hashbang apropriada ou executando bash your-script
explicitamente. É também o que você obtém quando você faz bash
executar um one-liner com a opção -c
, como:
bash -c 'echo hello world'
Como seria de esperar, o shell que você obtém quando efetua login via SSH para uma sessão interativa é um shell de login interativo. Isso é o que você obtém quando você executa um comando como este (supondo que seja bem-sucedido):
ssh [email protected]
Mas aqui é onde entra a parte não-intuitiva: o shell que você obtém quando você efetua login via SSH para uma sessão não-interativa é uma não-interativa < shell strong> não-login . Isso é o que você obtém executando um único comando via SSH:
ssh [email protected] command args...
Ou seja, executar um único comando via SSH executa bash
como o mesmo tipo de shell - um shell não interativo, não-login - como quando você executa um único comando localmente (ou dentro de um comando já estabelecido) sessão remota) usando bash -c
.
Como ssh
em geral, scp
faz com que um shell seja executado na máquina remota como o usuário remoto. Isso ainda é o que eles configuraram como shell, ou seja, o shell listado na entrada do usuário em /etc/passwd
ou a saída de getent passed
(que também é definida como o valor da variável de ambiente $SHELL
quando eles são registrados dentro). A menos que eles o tenham alterado executando chsh
, este é o shell padrão do usuário, que no Ubuntu é bash
.
É por isso que comandos como este executam um shell bash
não-interativo e não interativo no servidor remoto:
scp [email protected]:~/test.txt ./
A menos que sejam protegidos por código para parar se o shell não for interativo, os comandos em .bashrc
ou /etc/bash.bashrc
serão executados por tal shell. Se eles produzirem a saída - intencionalmente ou não - então o scp
não poderá copiar os arquivos .