Comment copier des fichiers nécessitant un accès root avec scp?

140

J'ai un serveur Ubuntu auquel je me connecte via SSH.

Je dois télécharger des fichiers de ma machine dans /var/www/ sur le serveur. Les fichiers de /var/www/ appartiennent à root .

Sous PuTTY, une fois connecté, je dois d'abord taper sudo su et mon mot de passe pour pouvoir modifier les fichiers dans /var/www/ .

Mais lorsque je copie des fichiers à l'aide de WinSCP, je ne peux pas créer / modifier de fichiers dans /var/www/ , car l'utilisateur avec lequel je me connecte ne dispose pas des autorisations nécessaires pour les fichiers dans /var/www/ et je ne peux pas dire. sudo su comme je le fais en cas de session SSH.

Savez-vous comment je pourrais gérer cela?

Si je travaillais sur ma machine locale, j'appellerais gksudo nautilus mais dans ce cas, je n'ai qu'un accès terminal à la machine.

    
posée Dimitris Sapikas 29.10.2012 - 22:03
la source

10 réponses

106

Vous avez raison, il n'y a pas sudo lorsque vous travaillez avec scp . Une solution de contournement consiste à utiliser scp pour télécharger des fichiers dans un répertoire dans lequel votre utilisateur dispose des autorisations nécessaires pour créer des fichiers, puis vous connecter via ssh et utiliser sudo pour déplacer / copier des fichiers vers leur destination finale.

scp -r folder/ user@server.tld:/some/folder/you/dont/need/sudo
ssh user@server.tld
 $ sudo mv /some/folder /some/folder/requiring/perms 
# YOU MAY NEED TO CHANGE THE OWNER like:
# sudo chown -R user:user folder

Une autre solution consisterait à modifier les autorisations / la propriété des répertoires dans lesquels vous téléchargez les fichiers afin que votre utilisateur non privilégié puisse y écrire.

En règle générale, travailler dans le compte root devrait être une exception et non une règle. Votre formulation de la question me fait penser que vous en abusez peut-être un peu, ce qui entraîne des problèmes d'autorisations, dans des conditions normales. circonstances, vous n'avez pas besoin de privilèges de super-administrateur pour accéder à vos propres fichiers.

Techniquement, vous pouvez configurer Ubuntu pour autoriser la connexion à distance directement en tant que root , mais cette fonctionnalité est désactivée pour une raison, je vous déconseille donc strongment de le faire.

    
réponse donnée Sergey 29.10.2012 - 23:22
la source
29

Une autre méthode consiste à copier en utilisant tar + ssh au lieu de scp:

tar -c -C ./my/local/dir \
  | ssh dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
    
réponse donnée Willie Wheeler 03.10.2014 - 20:56
la source
23

Vous pouvez également utiliser ansible pour accomplir cela.

Copier sur l'hôte distant à l'aide du module copy d'ansible :

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

Récupération de l'hôte distant à l'aide du module fetch d'ansible :

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

REMARQUE:

  • La virgule dans la syntaxe -i HOST, n'est pas une faute de frappe. C'est le moyen d'utiliser ansible sans avoir besoin d'un fichier d'inventaire.
  • -b provoque les actions sur le serveur en tant que root. -b se développe en --become et la valeur par défaut --become-user est root, la valeur par défaut --become-method étant sudo.
  • flat=yes copie seulement le fichier, ne copie pas le chemin d'accès distant complet menant au fichier
  • L'utilisation de caractères génériques dans les chemins de fichiers n'est pas prise en charge par ces modules ansible.
  • La copie d'un répertoire est prise en charge par le module copy , mais pas par le module fetch .

Invocation spécifique pour cette question

Voici un exemple spécifique et entièrement spécifié, en supposant que le répertoire de votre hôte local contenant les fichiers à distribuer est sourcedir et que le nom d'hôte de la cible distante est hostname :

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

L'invocation concise étant:

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

P.S., je me rends compte que dire "il suffit d'installer ce fabuleux outil" est une sorte de réponse ton sourde. Mais j’ai trouvé que super était toujours utile pour l’administration de serveurs distants, son installation vous apportera donc d’autres avantages que le déploiement de fichiers.

    
réponse donnée erik.weathers 15.02.2016 - 08:03
la source
12

Lorsque vous exécutez sudo su , tous les fichiers que vous créez seront la propriété de root, mais il n'est pas possible par défaut de se connecter directement en tant que root avec ssh ou scp. Il n’est pas possible non plus d’utiliser sudo avec scp, les fichiers ne sont donc pas utilisables. Résolvez ce problème en revendiquant la propriété de vos fichiers:

En supposant que votre nom d'utilisateur soit dimitri, vous pouvez utiliser cette commande.

sudo chown -R dimitri:dimitri /home/dimitri

À partir de là, comme mentionné dans d'autres réponses, la méthode "Ubuntu" consiste à utiliser sudo et non les connexions à la racine. C’est un paradigme utile, doté d’énormes avantages en matière de sécurité.

    
réponse donnée Bailey S 30.10.2012 - 00:07
la source
8

Le meilleur moyen consiste à utiliser rsync ( Cygwin / cwRsync sous Windows) sur SSH?

Par exemple, pour télécharger des fichiers avec le propriétaire www-data :

rsync -a --rsync-path="sudo -u www-data rsync" path_to_local_data/ login@srv01.example.com:/var/www

Dans votre cas, si vous avez besoin de privilèges root, la commande sera comme ceci:

rsync -a --rsync-path="sudo rsync" path_to_local_data/ login@srv01.example.com:/var/www

Voir: scp sur un serveur distant avec sudo .

    
réponse donnée Alexey Vazhnov 15.11.2016 - 11:14
la source
7

Rapidement moyen:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file
    
réponse donnée Anderson Lira 16.01.2017 - 14:01
la source
5

Si vous utilisez les outils OpenSSH au lieu de PuTTY, vous pouvez le faire en initiant le transfert de fichier scp sur le serveur avec sudo . Assurez-vous qu'un démon sshd est en cours d'exécution sur votre ordinateur local. Avec ssh -R , vous pouvez donner au serveur un moyen de contacter votre machine.

Sur votre ordinateur:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

En plus de vous connecter au serveur, cela transférera toutes les connexions établies sur le port 11111 du serveur vers le port 22 de votre ordinateur: le port sur lequel sshd est en écoute.

Sur le serveur, démarrez le transfert de fichier comme suit:

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .
    
réponse donnée bergoid 21.11.2016 - 17:52
la source
1

Vous pouvez utiliser le script que j'ai écrit en s'inspirant de ce sujet:

touch /tmp/justtest && scpassudo /tmp/justtest remoteuser@ssh.superserver.com:/tmp/

mais cela nécessite des trucs déjantés (ce qui est d'ailleurs fait automatiquement par le script)

  1. le serveur auquel le fichier est envoyé ne demandera plus de mot de passe lors de l'établissement de la connexion ssh à l'ordinateur source
  2. En raison de la nécessité de l'absence d'invite sudo sur le serveur, sudo ne demandera plus de mot de passe sur la machine distante, pour l'utilisateur

Voici le 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 remoteuser@ssh.superserver.com:/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
    
réponse donnée test30 21.11.2013 - 20:47
la source
1

Vous pouvez combiner ssh, sudo et, par exemple, tar pour transférer des fichiers entre serveurs sans pouvoir vous connecter en tant que root et ne pas être autorisé à accéder aux fichiers avec votre utilisateur. C'est un peu délicat, alors j'ai écrit un script pour aider ceci. Vous pouvez trouver le script ici: link

ou ici:

#! /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
    
réponse donnée sigmunda 01.07.2015 - 17:16
la source
0

Voici une version modifiée de la réponse de Willie Wheeler qui transfère le (s) fichier (s) via tar, mais permet également de passer un mot de passe à sudo sur l'hôte distant.

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

Le petit plus de magie ici est l’option -S de sudo. Sur la page de manuel 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.

Nous voulons maintenant que la sortie de tar soit acheminée vers ssh, ce qui redirige le stdin de ssh vers la sortie standard de tar, supprimant ainsi tout moyen de transmettre le mot de passe à sudo à partir du terminal interactif. (Nous pourrions utiliser la fonction ASKPASS de sudo sur le côté distant, mais ceci est une autre histoire.) Nous pouvons obtenir le mot de passe dans sudo en le capturant à l'avance et en l'ajoutant à la sortie du fichier tar en effectuant ces opérations dans un sous-shell et en transférant le sous-shell dans SSH. Cela présente également l’avantage supplémentaire de ne pas laisser une variable d’environnement contenant notre mot de passe suspendu dans notre shell interactif.

Vous remarquerez que je n'ai pas exécuté 'read' avec l'option -p pour imprimer une invite. En effet, l'invite de mot de passe de sudo est renvoyée de manière pratique à stderr de notre shell interactif via ssh. Vous vous demandez peut-être "comment sudo s’exécute-t-il étant donné qu’il s’exécute à l’intérieur de ssh, à droite de notre pipe?" Lorsque nous exécutons plusieurs commandes et que nous transmettons le résultat de l'une à l'autre, le shell parent (le shell interactif dans ce cas) exécute chaque commande dans la séquence immédiatement après l'exécution de la précédente. Au fur et à mesure que chaque commande située derrière un tube est exécutée, le shell parent attache (redirige) la sortie standard du côté gauche au standard stdin. La sortie devient alors une entrée à mesure qu'elle passe par des processus. Nous pouvons le voir en action en exécutant l'intégralité de la commande et en mettant en arrière-plan le groupe de processus (Ctrl-z) avant de saisir notre mot de passe, puis en affichant l'arbre de processus.

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

Notre shell interactif est le PID 7168, notre sous-shell est le PID 7969 et notre processus SSH est le PID 7970.

Le seul inconvénient est que read acceptera les entrées avant que sudo n’ait le temps de renvoyer son invite. Sur une connexion rapide et un hôte distant rapide, vous ne le remarquerez pas, mais vous pourriez le faire si l'un ou l'autre est lent. Tout retard n'affectera pas la possibilité d'entrer l'invite; il se peut qu’il apparaisse une fois que vous avez commencé à taper.

Remarque: j'ai simplement ajouté une entrée de fichier hôte pour "remote_Host" sur mon ordinateur local pour la démonstration.

    
réponse donnée Bruce 06.05.2017 - 12:17
la source

Lire d'autres questions sur les étiquettes