Como copio arquivos que precisam de acesso root com scp?

140

Eu tenho um servidor Ubuntu ao qual estou me conectando usando o SSH.

Eu preciso enviar arquivos da minha máquina para /var/www/ no servidor, os arquivos em /var/www/ são de propriedade de root .

Usando o PuTTY, depois de efetuar login, eu tenho que digitar sudo su e minha senha primeiro para poder modificar os arquivos em /var/www/ .

Mas quando estou copiando arquivos usando o WinSCP, não consigo criar / modificar arquivos em /var/www/ , porque o usuário com quem estou me conectando não tem permissões em arquivos em /var/www/ e não posso dizer sudo su como eu faço no caso de uma sessão ssh.

Você sabe como eu poderia lidar com isso?

Se eu estivesse trabalhando na minha máquina local, ligaria para gksudo nautilus , mas neste caso eu só tenho acesso ao terminal para a máquina.

    
por Dimitris Sapikas 29.10.2012 / 22:03

10 respostas

106

Você está certo, não há sudo ao trabalhar com scp . Uma solução alternativa é usar scp para fazer upload de arquivos para um diretório no qual o usuário tenha permissões para criar arquivos, faça login via ssh e use sudo para mover / copiar arquivos para o destino final.

scp -r folder/ [email protected]:/some/folder/you/dont/need/sudo
ssh [email protected]
 $ sudo mv /some/folder /some/folder/requiring/perms 
# YOU MAY NEED TO CHANGE THE OWNER like:
# sudo chown -R user:user folder

Outra solução seria alterar as permissões / propriedade dos diretórios nos quais você está enviando os arquivos, para que o usuário sem privilégios possa gravar nesses diretórios.

Geralmente, trabalhar na conta root deve ser uma exceção, não uma regra - a maneira como você formula sua pergunta me faz pensar que você está abusando um pouco, o que, por sua vez, leva a problemas com permissões - sob condições normais. circunstâncias você não precisa de privilégios de superadministrador para acessar seus próprios arquivos.

Tecnicamente, você pode configurar o Ubuntu para permitir login remoto diretamente como root , mas esse recurso está desabilitado por algum motivo, então eu aconselho strongmente que você faça isso.

    
por Sergey 29.10.2012 / 23:22
29

Outro método é copiar usando tar + ssh em vez de scp:

tar -c -C ./my/local/dir \
  | ssh [email protected] "sudo tar -x --no-same-owner -C /var/www"
    
por Willie Wheeler 03.10.2014 / 20:56
23

Você também pode usar ansible para fazer isso.

Copiar para o host remoto usando o módulo copy do ansible :

ansible -i HOST, -b -m copy -a "src=SRC_FILEPATH dest=DEST_FILEPATH" all

Buscar do host remoto usando o módulo fetch do ansible :

ansible -i HOST, -b -m fetch -a "src=SRC_FILEPATH dest=DEST_FILEPATH flat=yes" all

NOTA:

  • A vírgula na sintaxe -i HOST, não é um erro de digitação. É a maneira de usar ansible sem precisar de um arquivo de inventário.
  • -b faz com que as ações no servidor sejam feitas como raiz. -b expande para --become e o padrão --become-user é raiz, com o padrão --become-method sendo sudo.
  • flat=yes copia apenas o arquivo, não copia todo o caminho remoto que leva ao arquivo
  • O uso de curingas nos caminhos de arquivo não é suportado por esses módulos ansible.
  • Copiar um diretório é suportado pelo módulo copy , mas não pelo módulo fetch .

Invocação específica para esta questão

Veja um exemplo que é específico e totalmente especificado, supondo que o diretório em seu host local contendo os arquivos a serem distribuídos seja sourcedir e que o nome do host do destino remoto seja hostname :

cd sourcedir && \
ansible \
   --inventory-file hostname, \ 
   --become \
   --become-method sudo \
   --become-user root \
   --module-name copy \
   --args "src=. dest=/var/www/" \
   all

Com a invocação concisa sendo:

cd sourcedir && \
ansible -i hostname, -b -m copy -a "src=. dest=/var/www/" all

P.S., percebo que dizer "basta instalar essa ferramenta fabulosa" é uma espécie de resposta de tom surdo. Mas eu achei ansible ser super útil para administrar servidores remotos, então instalá-lo certamente trará outros benefícios além da implementação de arquivos.

    
por erik.weathers 15.02.2016 / 08:03
12

Quando você executar sudo su , todos os arquivos que você criar serão de propriedade de root, mas não é possível fazer login como root com ssh ou scp. Também não é possível usar o sudo com o scp, então os arquivos não são utilizáveis. Corrija isso reivindicando propriedade sobre seus arquivos:

Supondo que seu nome de usuário fosse dimitri, você poderia usar este comando.

sudo chown -R dimitri:dimitri /home/dimitri

A partir daí, como mencionado em outras respostas, o modo "Ubuntu" é usar o sudo, e não logins root. É um paradigma útil, com grandes vantagens de segurança.

    
por Bailey S 30.10.2012 / 00:07
8

Pode ser a melhor maneira de usar rsync ( Cygwin / cwRsync no Windows) em SSH?

Por exemplo, para enviar arquivos com o proprietário www-data :

rsync -a --rsync-path="sudo -u www-data rsync" path_to_local_data/ [email protected]:/var/www

No seu caso, se você precisar de privilégios de root, o comando será assim:

rsync -a --rsync-path="sudo rsync" path_to_local_data/ [email protected]:/var/www

Veja: scp para o servidor remoto com sudo .

    
por Alexey Vazhnov 15.11.2016 / 11:14
7

Rapidamente:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file
    
por Anderson Lira 16.01.2017 / 14:01
5

Se você usar as ferramentas OpenSSH em vez de PuTTY, poderá fazer isso iniciando a transferência de arquivos scp no servidor com sudo . Certifique-se de ter um daemon sshd em execução na sua máquina local. Com ssh -R , você pode fornecer ao servidor uma maneira de entrar em contato com sua máquina.

Na sua máquina:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Além de fazer login no servidor, isso encaminhará todas as conexões feitas na porta 11111 do servidor para a porta 22 da sua máquina: a porta na qual o sshd está escutando.

No servidor, inicie a transferência de arquivos assim:

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .
    
por bergoid 21.11.2016 / 17:52
1

Você pode usar o script que escrevi inspirado por este tópico:

touch /tmp/justtest && scpassudo /tmp/justtest [email protected]:/tmp/

mas isso requer algumas coisas malucas (o que é feito automaticamente pelo script)

  1. servidor para o qual o arquivo está sendo enviado não solicitará mais a senha ao estabelecer a conexão ssh com o computador de origem
  2. devido a necessidade de falta de sudo prompt no servidor, o sudo não pedirá mais senha na máquina remota, para usuário

Aqui vai o script:

interface=wlan0
if [[ $# -ge 3 ]]; then interface=$3; fi
thisIP=$(ifconfig | grep $interface -b1 | tail -n1 | egrep -o '[0-9.]{4,}' -m1 | head -n 1)
thisUser=$(whoami)
localFilePath=/tmp/justfortest
destIP=192.168.0.2
destUser=silesia
#dest 
#destFolderOnRemoteMachine=/opt/glassfish/glassfish/
#destFolderOnRemoteMachine=/tmp/

if [[ $# -eq 0 ]]; then 
echo -e "Send file to remote server to locatoin where root permision is needed.\n\tusage: $0 local_filename [username@](ip|host):(remote_folder/|remote_filename) [optionalInterface=wlan0]"
echo -e "Example: \n\ttouch /tmp/justtest &&\n\t $0 /tmp/justtest [email protected]:/tmp/ "
exit 1
fi

localFilePath=$1

test -e $localFilePath 

destString=$2
usernameAndHost=$(echo $destString | cut -f1 -d':')

if [[ "$usernameAndHost" == *"@"* ]]; then
destUser=$(echo $usernameAndHost | cut -f1 -d'@')
destIP=$(echo $usernameAndHost | cut -f2 -d'@')
else
destIP=$usernameAndHost
destUser=$thisUser
fi

destFolderOnRemoteMachine=$(echo $destString | cut -f2 -d':')

set -e #stop script if there is even single error

echo 'First step: we need to be able to execute scp without any user interaction'
echo 'generating public key on machine, which will receive file'
ssh $destUser@$destIP 'test -e ~/.ssh/id_rsa.pub -a -e ~/.ssh/id_rsa || ssh-keygen -t rsa'
echo 'Done'

echo 'Second step: download public key from remote machine to this machine so this machine allows remote machine (this one receiveing file) to login without asking for password'

key=$(ssh $destUser@$destIP 'cat ~/.ssh/id_rsa.pub')
if ! grep "$key" ~/.ssh/authorized_keys; then
echo $key >> ~/.ssh/authorized_keys
echo 'Added key to authorized hosts'
else
echo "Key already exists in authorized keys"
fi

echo "We will want to execute sudo command remotely, which means turning off asking for password"
echo 'This can be done by this tutorial http://stackoverflow.com/a/10310407/781312'
echo 'This you have to do manually: '
echo -e "execute in new terminal: \n\tssh $destUser:$destIP\nPress enter when ready"
read 
echo 'run there sudo visudo'
read
echo 'change '
echo '    %sudo   ALL=(ALL:ALL) ALL'
echo 'to'
echo '    %sudo   ALL=(ALL:ALL) NOPASSWD: ALL'
echo "After this step you will be done."
read

listOfFiles=$(ssh $destUser@$destIP "sudo ls -a")

if [[ "$listOfFiles" != "" ]]; then 
echo "Sending by executing command, in fact, receiving, file on remote machine"
echo 'Note that this command (due to " instead of '', see man bash | less -p''quotes'') is filled with values from local machine'
echo -e "Executing \n\t""identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"" \non remote machine"
ssh $destUser@$destIP "identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"
ssh $destUser@$destIP "ls ${destFolderOnRemoteMachine%\\n}/$(basename $localFilePath)"
if [[ ! "$?" -eq 0 ]]; then echo "errror in validating"; else echo -e "SUCCESS! Successfully sent\n\t$localFilePath \nto \n\t$destString\nFind more at http://arzoxadi.tk"; fi
else
echo "something went wrong with executing sudo on remote host, failure"

fi
ENDOFSCRIPT
) | sudo tee /usr/bin/scpassudo && chmod +x /usr/bin/scpassudo
    
por test30 21.11.2013 / 20:47
1

Você pode combinar ssh, sudo e, por exemplo, tar para transferir arquivos entre servidores sem poder fazer login como root e não ter permissão para acessar os arquivos com seu usuário. Isso é um pouco complicado, então escrevi um script para ajudar nisso. Você pode encontrar o script aqui: link

ou aqui:

#! /bin/bash
res=0
from=$1
to=$2
shift
shift
files="$@"
if test -z "$from" -o -z "$to" -o -z "$files"
then
    echo "Usage: $0    (file)*"
    echo "example: $0 server1 server2 /usr/bin/myapp"
    exit 1
fi

read -s -p "Enter Password: " sudopassword
echo ""
temp1=$(mktemp)
temp2=$(mktemp)
(echo "$sudopassword";echo "$sudopassword"|ssh $from sudo -S tar c -P -C / $files 2>$temp1)|ssh $to sudo -S tar x -v -P -C / 2>$temp2
sourceres=${PIPESTATUS[0]}
if [ $? -ne 0 -o $sourceres -ne 0 ]
then
    echo "Failure!" >&2
    echo "$from output:" >&2
    cat $temp1 >&2
    echo "" >&2
    echo "$to output:" >&2
    cat $temp2 >&2
    res=1
fi

rm $temp1 $temp2
exit $res
    
por sigmunda 01.07.2015 / 17:16
0

Aqui está uma versão modificada da resposta de Willie Wheeler, que transfere o (s) arquivo (s) via tar, mas também suporta a passagem de uma senha para o sudo no host remoto.

(stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) \
  | ssh remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""

O pouco de mágica extra aqui é a opção -S para o sudo. Da página de manual do sudo:

-S, --stdin Write the prompt to the standard error and read the password from the standard input instead of using the terminal device. The password must be followed by a newline character.

Agora, queremos que a saída do tar seja canalizada para o ssh e redirecione o stdin do ssh para o stdout do tar, removendo qualquer forma de passar a senha para o sudo a partir do terminal interativo. (Poderíamos usar o recurso ASKPASS do sudo no terminal remoto, mas isso é outra história.) Podemos obter a senha no sudo, capturando-a antecipadamente e anexando-a à saída tar executando essas operações em uma subcamada e canalizando a saída de o subshell em ssh. Isso também tem a vantagem de não deixar uma variável de ambiente contendo nossa senha pendurada em nosso shell interativo.

Você notará que eu não executei 'read' com a opção -p para imprimir um prompt. Isso ocorre porque o prompt de senha do sudo é convenientemente passado de volta para o stderr do nosso shell interativo via ssh. Você pode se perguntar "como está a execução do sudo dado que ele está rodando dentro do ssh à direita do nosso pipe?" Quando executamos vários comandos e canalizamos a saída de um para outro, o shell pai (o shell interativo neste caso) executa cada comando na sequência imediatamente após a execução do anterior. Como cada comando atrás de um pipe é executado, o shell pai anexa (redireciona) a stdout do lado esquerdo para o stdin do lado direito. A saída se torna entrada à medida que passa pelos processos. Podemos ver isso em ação, executando todo o comando e fazendo o background do grupo de processos (Ctrl-z) antes de digitar nossa senha e, em seguida, visualizando a árvore de processos.

$ (stty -echo; read passwd; stty echo; echo $passwd; tar -cz foo.*) | ssh 
remote_host "sudo -S bash -c \"tar -C /var/www/ -xz; echo\""
[sudo] password for bruce: 
[1]+  Stopped                 ( stty -echo; read passwd; stty echo; echo 
$passwd; tar -cz foo.* ) | ssh remote_host "sudo -S bash -c \"tar -C 
/var/www/ -xz; echo\""

$ pstree -lap $$
bash,7168
  ├─bash,7969
  ├─pstree,7972 -lap 7168
  └─ssh,7970 remote_host sudo -S bash -c "tar -C /var/www/ -xz; echo"'

Nosso shell interativo é o PID 7168, nosso subshell é o PID 7969 e nosso processo ssh é o PID 7970.

O único inconveniente é que a leitura aceita entrada antes que o sudo tenha tempo de enviar o prompt de volta. Em uma conexão rápida e rápida hospedagem remota você não vai perceber isso, mas você pode se está lento. Qualquer atraso não afetará a capacidade de inserir o prompt; só pode aparecer depois que você começou a digitar.

Note que eu simplesmente adicionei uma entrada de arquivo host para "remote_Host" na minha máquina local para a demonstração.

    
por Bruce 06.05.2017 / 12:17