¿Cómo copio archivos que necesitan acceso de root con scp?

140

Tengo un servidor Ubuntu al que me estoy conectando mediante SSH.

Necesito cargar archivos de mi máquina en /var/www/ en el servidor, los archivos en /var/www/ son propiedad de root .

Al usar PuTTY, después de iniciar sesión, primero debo ingresar sudo su y mi contraseña para poder modificar los archivos en /var/www/ .

Pero cuando estoy copiando archivos usando WinSCP, no puedo crear / modificar archivos en /var/www/ , porque el usuario con el que me estoy conectando no tiene permisos para archivos en /var/www/ y no puedo decir sudo su como hago en caso de una sesión ssh.

¿Sabes cómo podría lidiar con esto?

Si estuviera trabajando en mi máquina local, llamaría gksudo nautilus pero en este caso solo tengo acceso de terminal a la máquina.

    
pregunta Dimitris Sapikas 29.10.2012 - 22:03

10 respuestas

106

Tienes razón, no hay sudo cuando trabajas con scp . Una solución es usar scp para cargar archivos a un directorio donde su usuario tenga permisos para crear archivos, luego inicie sesión a través de ssh y use sudo para mover / copiar archivos a su 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

Otra solución sería cambiar los permisos / propiedad de los directorios en los que subes los archivos, para que tu usuario sin privilegios pueda escribir en esos directorios.

Por lo general, trabajar en la cuenta root debería ser una excepción, no una regla, la forma en que redactas tu pregunta me hace pensar que quizás estés abusando de ella un poco, lo que a su vez genera problemas con los permisos. En algunas circunstancias, no necesita privilegios de superadministrador para acceder a sus propios archivos.

Técnicamente, puedes configurar Ubuntu para permitir el inicio de sesión remoto directamente como root , pero esta función está deshabilitada por una razón, por lo que te recomiendo que no hagas eso.

    
respondido por el Sergey 29.10.2012 - 23:22
29

Otro método es copiar usando tar + ssh en lugar de scp:

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

También puedes usar ansible para lograr esto.

Copie al host remoto usando módulo copy de ansible :

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

Recuperar desde el host remoto utilizando módulo fetch de ansible :

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

NOTA:

  • La coma en la sintaxis -i HOST, no es un error tipográfico. Es la forma de usar ansible sin necesidad de un archivo de inventario.
  • -b hace que las acciones en el servidor se realicen como root. -b se expande a --become , y el --become-user predeterminado es la raíz, con el --become-method predeterminado siendo sudo.
  • flat=yes copia solo el archivo, no copia toda la ruta remota que lleva al archivo
  • El uso de comodines en las rutas de archivo no es compatible con estos módulos ansible.
  • Copiar un directorio es admitido por el módulo copy , pero no por el módulo fetch .

Invocación específica para esta pregunta

Este es un ejemplo que es específico y está completamente especificado, asumiendo que el directorio en su host local que contiene los archivos que se distribuirán es sourcedir , y que el nombre de host del destino remoto es hostname :

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

Con la invocación concisa es:

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

P.S., me doy cuenta de que decir "solo instale esta fabulosa herramienta" es una especie de respuesta de tono sordo. Pero puedo encontrar que super sea útil para administrar servidores remotos, por lo que su instalación seguramente le brindará otros beneficios más allá de la implementación de archivos.

    
respondido por el erik.weathers 15.02.2016 - 08:03
12

Cuando ejecuta sudo su , todos los archivos que cree serán propiedad de root, pero de forma predeterminada no es posible iniciar sesión directamente como root con ssh o scp. Tampoco es posible usar sudo con scp, por lo que los archivos no son utilizables. Solucione esto reclamando la propiedad sobre sus archivos:

Suponiendo que su nombre de usuario fuera dimitri, podría usar este comando.

sudo chown -R dimitri:dimitri /home/dimitri

De ahí en adelante, como se mencionó en otras respuestas, la forma "Ubuntu" es usar sudo, y no los inicios de sesión de root. Es un paradigma útil, con grandes ventajas de seguridad.

    
respondido por el trognanders 30.10.2012 - 00:07
8

Puede que la mejor manera sea usar rsync ( Cygwin / cwRsync en Windows) sobre SSH?

Por ejemplo, para cargar archivos con el propietario www-data :

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

En su caso, si necesita privilegios de root, el comando será así:

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

Consulte: scp al servidor remoto con sudo .

    
respondido por el Alexey Vazhnov 15.11.2016 - 11:14
7

Vía rápida:

ssh [email protected] "sudo cat /etc/dir/file" > /home/user/file
    
respondido por el Anderson Lira 16.01.2017 - 14:01
5

Si usa las herramientas OpenSSH en lugar de PuTTY, puede lograr esto al iniciar la transferencia de archivos scp en el servidor con sudo . Asegúrese de tener un daemon sshd ejecutándose en su máquina local. Con ssh -R puede darle al servidor una forma de comunicarse con su máquina.

En tu máquina:

ssh -R 11111:localhost:22 [email protected]

Además de iniciar sesión en el servidor, esto reenviará todas las conexiones realizadas en el puerto 11111 del servidor al puerto 22 de su máquina: el puerto en el que escucha su sshd .

En el servidor, inicie la transferencia de archivos de esta manera:

cd /var/www/
sudo scp -P 11111 -r [email protected]:FOLDERNAME .
    
respondido por el bergoid 21.11.2016 - 17:52
1

Puedes usar el script que he escrito inspirándome en este tema:

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

pero esto requiere algunas cosas locas (que es por cierto hecho automáticamente por script)

  1. el servidor al que se envía el archivo ya no solicitará la contraseña al establecer la conexión ssh con la computadora fuente
  2. debido a la necesidad de falta de aviso de sudo en el servidor, sudo ya no solicitará la contraseña en la máquina remota, para el usuario

Aquí va el guión:

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 [[email protected]](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 [email protected]$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 [email protected]$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 [email protected]$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 [email protected]$destIP "identy=~/.ssh/id_rsa; sudo scp -i \$identy $(whoami)@$thisIP:$(readlink -f $localFilePath) $destFolderOnRemoteMachine"
ssh [email protected]$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
    
respondido por el test30 21.11.2013 - 20:47
1

Puede combinar ssh, sudo y, por ejemplo, tar para transferir archivos entre servidores sin poder iniciar sesión como root y no tener permiso para acceder a los archivos con su usuario. Esto es un poco complicado, así que he escrito un guión para ayudar a esto. Puede encontrar el script aquí: enlace

o aquí:

#! /bin/bash
res=0
from=$1
to=$2
shift
shift
files="[email protected]"
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
    
respondido por el sigmunda 01.07.2015 - 17:16
0

Aquí hay una versión modificada de la respuesta de Willie Wheeler que transfiere los archivos a través de tar, pero también permite pasar una contraseña a sudo en el 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\""

El poco de magia extra aquí es la opción -S para sudo. Desde la página del manual de sudo:

  

-S, --stdin                    Escriba la solicitud al error estándar y lea la contraseña de la entrada estándar en lugar de usar el dispositivo terminal. La contraseña debe ir seguida de un carácter de nueva línea.

Ahora queremos que la salida de tar se canalice a ssh y eso redirige el stdin de ssh al stdout de tar, eliminando cualquier forma de pasar la contraseña a sudo desde el terminal interactivo. (Podríamos usar la función ASKPASS de sudo en el extremo remoto, pero esa es otra historia). Podemos obtener la contraseña en sudo capturándola por adelantado y añadiéndola a la salida de tar realizando esas operaciones en una subshell y canalizando la salida de la subshell en ssh. Esto también tiene la ventaja adicional de no dejar una variable de entorno que contiene nuestra contraseña en nuestra shell interactiva.

Notarás que no ejecuté "lectura" con la opción -p para imprimir un aviso. Esto se debe a que la solicitud de contraseña de sudo se transfiere convenientemente al stderr de nuestra shell interactiva a través de ssh. Podría preguntarse "¿cómo se está ejecutando sudo dado que se está ejecutando dentro de ssh a la derecha de nuestra tubería?" Cuando ejecutamos varios comandos y canalizamos la salida de uno a otro, el shell primario (el shell interactivo en este caso) ejecuta cada comando en la secuencia inmediatamente después de ejecutar el anterior. A medida que se ejecuta cada comando detrás de una tubería, el shell primario adjunta (redirecciona) la salida estándar del lado izquierdo al stdin del lado derecho. La salida se convierte en entrada a medida que pasa a través de los procesos. Podemos ver esto en acción ejecutando todo el comando y seleccionando el fondo del grupo de procesos (Ctrl-z) antes de escribir nuestra contraseña y luego ver el árbol de procesos.

$ (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"'

Nuestro shell interactivo es PID 7168, nuestra subshell es PID 7969 y nuestro proceso ssh es PID 7970.

El único inconveniente es que la lectura aceptará la entrada antes de que sudo tenga tiempo de devolver su mensaje. En una conexión rápida y en un host remoto rápido, no notará esto, pero es posible que cualquiera de los dos sea lento. Cualquier demora no afectará la capacidad de ingresar al prompt; puede que aparezca después de que hayas comenzado a escribir.

Nota: simplemente agregué una entrada de archivo de host para "remote_Host" a mi máquina local para la demostración.

    
respondido por el Bruce 06.05.2017 - 12:17

Lea otras preguntas en las etiquetas