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

168

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

J'ai besoin de télécharger des fichiers de ma machine /var/www/sur le serveur, ceux /var/www/-ci appartenant à root.

À l’aide de PuTTY, une fois connecté (e), je dois d'abord taper sudo sumon mot de passe pour pouvoir modifier les fichiers /var/www/.

Mais lorsque je copie des fichiers à l'aide de WinSCP, je ne peux pas créer / modifier de fichiers /var/www/, car l'utilisateur avec lequel je me connecte n'a pas d'autorisations sur les fichiers /var/www/et je ne peux pas dire ce sudo suque je fais dans le cas d'une session SSH. .

Savez-vous comment je pourrais gérer cela?

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

Dimitris Sapikas
la source
Cela ressemble plus à une question pour votre fournisseur de serveur virtuel, ou pour les développeurs de putty ou de winscp.
Dobey
7
@ dobey vous vous trompez évidemment, il s'agit des privilèges Ubuntu!
Dimitris Sapikas
7
Pourquoi est-ce fermé? Ceci est une question tout à fait valable à propos de la copie de fichiers avec scp - tous les développeurs web sont familiers avec cette situation
Sergey
J'ai le même problème. Je crée un fichier (HTML dans ce cas) sur un ordinateur Windows et essaie de le copier avec WinSCP dans le dossier / var / www / html / website. Et il dit qu'il y a un problème de permission. Parce que je peux copier dans mon dossier / home, j'ai copié le fichier en deux étapes, mais ce n'est pas très pratique :-) J'ai essayé d'ajouter mon utilisateur au groupe www-data, mais cela n'a pas aidé. Pourquoi ne pas ajouter un utilisateur à www-data ne permet toujours pas à l'utilisateur de copier un fichier dans un dossier appartenant à www-data group?
JanezKranjski le

Réponses:

126

Vous avez raison, il n'y a pas de sudotravail avec scp. Une solution de contournement consiste à scpté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 sudopour déplacer / copier des fichiers vers leur destination finale.

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

Une autre solution serait de 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 écrire dans ces répertoires.

En règle générale, travailler dans le rootcompte doit être une exception et non une règle. La formulation de votre question me fait penser que vous en abusez peut-être un peu, ce qui entraîne des problèmes d'autorisations. Dans des circonstances normales, vous n'avez pas besoin de cela. 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 fortement de le faire.

Sergey
la source
Je n'ai pas eu la première solution, pourriez-vous s'il vous plaît être un peu plus spécifique?
Dimitris Sapikas
Whe je dis mes propres fichiers je veux dire / var / www, j'utilise mon vps en tant que serveur Web .... sur mon propre dossier, j'ai un accès complet
Dimitris Sapikas
7
Ré. la première solution. 1. scp -R mysite [email protected]:/home/dimitris/2. ssh [email protected]3. sudo mv ~/mysite /var/www- c'est un processus en 2 étapes, vous devez d'abord scpenregistrer les fichiers dans votre répertoire personnel, puis vous connecter via ssh et copier / déplacer les fichiers là où ils devraient être
Sergey
36

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

tar -c -C ./my/local/dir \
  | ssh [email protected] "sudo tar -x --no-same-owner -C /var/www"
Willie Wheeler
la source
2
C'est la meilleure façon de le faire.
mttdbrd
2
Je n'arrive pas à faire fonctionner cette méthode avec succès. Comme écrit je reçois sudo: sorry, you must have a tty to run sudo. Si j'ajoute "-t" pour allouer un ATS, je reçois Pseudo-terminal will not be allocated because stdin is not a terminal.. Je ne peux pas voir cela fonctionner sans sudo sans mot de passe.
IBBoard
1
@IBBoard: essayez la solution ici en utilisant ssh -t:ssh -t [email protected] "sudo tar -x --no-same-owner -C /var/www"
Alexander Bird
2
@AlexanderBird Bien que cela fonctionne dans de nombreux cas, je ne suis pas sûr que cela fonctionne ici car nous essayons de diriger une archive par la connexion SSH. Voir serverfault.com/questions/14389/…
IBBoard
C'est ce qui a finalement fonctionné pour moi. Vous ne disposez pas des autorisations à un fichier distant que vous souhaitez copier au niveau local, faire sudo tar, archiver, modifier les autorisations à l' aide chmodet chown, puis copiez - le au niveau local. Surtout si c'est un répertoire.
forumulateur
28

Façon rapide

Du serveur à la machine locale:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file

De la machine locale au serveur:

cat /home/user/file | ssh user@server "sudo tee -a /etc/dir/file"
Anderson Lira
la source
5
Cette réponse est sous-estimée. C'est simple, propre, lit ou écrit un fichier racine avec une seule opération atomique, et ne nécessite rien qui ne soit déjà garanti si vous utilisez scp. Le principal inconvénient est qu'il ne copie pas les autorisations. Si vous le souhaitez, la solution tar est préférable. C'est une technique puissante, particulièrement si elle est combinée avec la magie xargs / bash pour parcourir des chemins ..
markgo2k
Je pense que la question portait sur le téléchargement d'un fichier de local à distant et non l'inverse
Korayem
1
Magnifiquement fait. C'est exactement ce que je cherchais de haut en bas. Merci
Jeremy
Mérite d'être la meilleure réponse, à coup sûr.
Andrew Watson
Cela peut-il être fait pour un répertoire au lieu d'un fichier?
lucidbrot
26

Vous pouvez également utiliser ansiblepour accomplir cela.

Copier vers un hôte distant en utilisant le copymodule ansible :

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

Récupérer depuis un hôte distant en utilisant le fetchmodule ansible :

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

REMARQUE:

  • La virgule dans la -i HOST,syntaxe n'est pas une faute de frappe. C'est la façon d'utiliser ansible sans avoir besoin d'un fichier d'inventaire.
  • -bprovoque les actions sur le serveur en tant que root. -bse développe en --become, et la valeur par défaut --become-userest root, la valeur par défaut --become-methodétant sudo.
  • flat=yescopie uniquement le fichier, ne copie pas le chemin d'accès 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 copymodule, mais pas par le fetchmodule.

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 le même sourcedirque le nom d'hôte de la cible distante hostname:

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

Avec l'invocation concise étant:

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

PS, je me rends compte que dire "viens d'installer ce fabuleux outil" est une sorte de réponse insensée. Mais j’ai trouvé ansible très utile pour l’administration de serveurs distants. Son installation vous apportera donc d’autres avantages que le déploiement de fichiers.

erik.weathers
la source
J'aime cette réponse, mais je vous recommande de vous adresser directement à la question posée plutôt qu’à un commentaire plus généralisé avant le vote par appel nominal. quelque chose commeansible -i "hostname," all -u user --become -m copy -a ...
Mike D
@MikeD: à quoi ressemblent les changements ci-dessus?
erik.weathers
1
Est-ce que quelque chose comme -i 'host,'être une syntaxe valide? Je pense qu'il est facile de perdre une ponctuation comme celle-ci lors de la lecture d'une commande. (Pour le lecteur, je veux dire, sinon la coquille.)
mwfearnley
1
@ mwfearnley: bien sûr, la coque va traiter -i 'host,'et pareil que -i host,ou -i "host,". En général, je préfère garder ces invocations aussi courtes que possible pour ne pas les décourager, mais vous devez vous sentir libre de les rendre aussi verbeuses et explicites que nécessaire, à des fins de clarté.
erik.weathers
2
Chemin à parcourir pour sortir des sentiers battus! Excellente utilisation de Ansible
Jonatan le
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 vous connecter directement en tant que root avec ssh ou scp. Il n'est également pas possible d'utiliser sudo avec scp, les fichiers ne sont donc pas utilisables. Corrigez cela 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, avec de grands avantages en termes de sécurité.

trognanders
la source
J'utilise cette solution de toute façon, mais si je pouvais obtenir un accès complet à mon propre système de fichiers, je ne voudrais pas taper sudo chow ...pour chaque répertoire: S
Dimitris Sapikas
2
Il est fortement déconseillé de changer la propriété de tous les fichiers système en faveur de l’utilisateur. Il permet à tout bogue d’espace utilisateur que vous pourriez rencontrer de compromettre gravement la sécurité de votre système. Il est bien préférable de changer la propriété des fichiers que vous avez besoin de changer ou de mettre à jour par SCP, mais de laisser tout le reste à la propriété de root (comme cela est censé l’être). Cela dit, l' -Rin en lui chowndit de changer la propriété de ce répertoire, ainsi que tous les fichiers et répertoires enfants de manière récursive ... afin que vous puissiez faire tout ce que vous voulez.
Trognanders
hmm .... ça a l'air de bien marcher, merci! désolé je ne peux pas voter (le système ne me permet pas de le faire ...)
Dimitris Sapikas
11

Peut-être le meilleur moyen est d'utiliser rsync( Cygwin / cwRsync dans 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/ [email protected]:/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/ [email protected]:/var/www

Voir: scp au serveur distant avec sudo .

Alexey Vazhnov
la source
5

Si vous utilisez les outils OpenSSH au lieu de PuTTY, vous pouvez le faire en lançant le scptransfert de fichier sur le serveur sudo. Assurez-vous qu'un sshddémon est en cours d'exécution sur votre ordinateur local. Avec, ssh -Rvous pouvez donner au serveur un moyen de contacter votre machine.

Sur votre machine:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

En plus de vous connecter au serveur, cela transférera chaque connexion établie sur le port 11111 du serveur vers le port 22 de votre ordinateur: le port sur lequel vous êtes en sshdtrain d'écouter.

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

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .
bergoïde
la source
1

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

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

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

  1. le serveur auquel le fichier est envoyé ne demandera plus de mot de passe lors de l'établissement d'une 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 [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
test30
la source
@Braiam ouais, bien sûr, désolé pour le lien, le script est assez long et c'était la raison :)
test30
1

Vous pouvez combiner ssh, sudo et, par exemple, tar pour transférer des fichiers entre serveurs sans pouvoir se connecter en tant que root et ne pas avoir l'autorisation d'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: https://github.com/sigmunau/sudoscp

ou ici:

#! / bin / bash
res = 0
à partir de = 1 $
à = 2 $
décalage
décalage
fichiers = "$ @"
si test -z "$ de" -o -z "$ à" -o -z "$ fichiers"
ensuite
    echo "Utilisation: 0 $ (fichier) *"
    echo "exemple: $ 0 serveur1 serveur2 / usr / bin / myapp"
    sortie 1
Fi

read -s -p "Enter Password:" sudopassword
écho ""
temp1 = $ (mktemp)
temp2 = $ (mktemp)
(echo "$ sudopassword"; echo "$ sudopassword" | ssh $ de sudo -S tar c -P - $ fichiers 2> $ temp1) | ssh $ vers sudo -S tar x -v -P -C / 2 > $ temp2
sourceres = $ {PIPESTATUS [0]}
si [$? -ne 0 -o $ sourceres -ne 0]
ensuite
    echo "Echec!" > & 2
    echo "$ from output:"> & 2
    chat $ temp1> & 2
    echo ""> & 2
    echo "$ to output:"> & 2
    chat $ temp2> & 2
    res = 1
Fi

rm $ temp1 $ temp2
sortie $ res
Sigmunda
la source
Bienvenue sur Ask Ubuntu. Pourriez-vous s'il vous plaît inclure le script dans votre réponse? Je sais que c'est peu probable, mais si le dépôt github avait déjà été supprimé ou si l'URL avait été modifiée, la réponse serait nulle. Il est préférable d’inclure le script directement et de laisser le dépôt github en tant que source.
Michael Lindman
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 transmettre 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. De la page de manuel sudo:

-S, --stdin Ecrit l'invite sur l'erreur standard et lit le mot de passe à partir de l'entrée standard au lieu d'utiliser le terminal. Le mot de passe doit être suivi d'un caractère de nouvelle ligne.

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 redirigeant la sortie du fichier. 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 dans la mesure où il s’exécute dans ssh, à droite de notre pipe?" Lorsque nous exécutons plusieurs commandes et que nous transmettons la sortie 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.

$ (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 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 pourrait juste apparaître après que vous ayez commencé à taper.

Remarque J'ai simplement ajouté une entrée de fichier hôte pour "remote_Host" à ma machine locale pour la démo.

Bruce
la source