Vraag Hoe kopieer ik bestanden die root-toegang nodig hebben met scp?


Ik heb een Ubuntu-server waarmee ik verbinding maak via SSH.

Ik moet bestanden van mijn computer uploaden naar /var/www/ op de server, de bestanden in /var/www/ zijn eigendom van root.

Met behulp van PuTTY, nadat ik me heb aangemeld, moet ik typen sudo su en mijn wachtwoord als eerste om bestanden in te kunnen wijzigen /var/www/.

Maar als ik bestanden kopieert met WinSCP, kan ik geen bestanden maken / wijzigen in /var/www/, omdat de gebruiker met wie ik verbinding maak geen rechten op bestanden in heb /var/www/ en ik kan niet zeggen sudo su zoals ik doe in het geval van een ssh-sessie.

Weet je hoe ik hiermee zou kunnen omgaan?

Als ik aan het werk was op mijn lokale computer, zou ik bellen gksudo nautilus maar in dit geval heb ik alleen terminal-toegang tot de machine.


134
2017-10-29 21:03


oorsprong


Dit lijkt meer op een vraag voor uw virtuele serverprovider of voor de stopverf- of winscp-ontwikkelaars. - dobey
@dobey je obviusly verkeerd, het gaat over ubuntu privileges! - Dimitris Sapikas
Waarom is dit gesloten? Dit is een volkomen geldige vraag over het kopiëren van bestanden met scp - elke webontwikkelaar is bekend met deze situatie - Sergey
Beveiligde bestanden kopiëren tussen servers op één regel? zou moeten helpen. - Gilles
Ik heb een soortgelijk probleem. Ik maak een bestand (in dit geval HTML) op een Windows-computer en probeer het te kopiëren met WinSCP naar / var / www / html / website map. En er staat dat er een probleem met de toestemming is. Omdat ik naar mijn / thuismap kan kopiëren, heb ik het bestand in twee stappen gekopieerd, maar het is niet erg handig :-) Ik probeerde met het toevoegen van mijn gebruiker aan www-gegevensgroep, maar het hielp niet. Enig idee waarom het toevoegen aan de gebruiker van www-gegevens nog steeds niet toestaat dat de gebruiker een bestand kopieert naar een map die eigendom is van de www-datagroep? - JanezKranjski


antwoorden:


Je hebt gelijk, er is geen sudo bij het werken met scp. Een oplossing is om te gebruiken scp om bestanden te uploaden naar een map waar uw gebruiker rechten heeft om bestanden te maken, log dan in via ssh en gebruik sudo om bestanden naar hun eindbestemming te verplaatsen / kopiëren.

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

Een andere oplossing zou zijn om de machtigingen / eigendomsrechten te wijzigen van de mappen waarnaar u de bestanden uploadt, zodat uw niet-bevoorrechte gebruiker in staat is om naar die mappen te schrijven.

Over het algemeen werkt u in de root account zou een uitzondering moeten zijn, geen regel - de manier waarop je je vraag formuleert maakt me aan het denken dat je het misschien een beetje misbruikt, wat op zijn beurt leidt tot problemen met permissies - onder normale omstandigheden heb je geen super-admin privileges nodig om toegang tot uw eigen bestanden.

Technisch gezien kunt u Ubuntu zo configureren dat inloggen op afstand rechtstreeks mogelijk is als root, maar deze functie is om een ​​bepaalde reden uitgeschakeld, dus ik raad je ten zeerste af om dat te doen.


105
2017-10-29 22:22



ik kreeg de eerste oplossing niet, zou je alsjeblieft wat korter kunnen zijn? - Dimitris Sapikas
Ik zeg mijn eigen bestanden, bedoel / var / www, ik gebruik mijn vps als webserver .... in mijn eigen map heb ik volledige toegang - Dimitris Sapikas
Opnieuw. de eerste oplossing. 1. scp -R mysite dimitris@myserver.com:/home/dimitris/ 2. ssh dimitris@myserver.com 3. sudo mv ~/mysite /var/www - het is een proces in twee stappen, eerst jij scp de bestanden naar je huis, dan meld je je aan via ssh en kopieer / verplaats je de bestanden naar waar ze zouden moeten zijn - Sergey
hm .. het werkt goed! dank je :) - Dimitris Sapikas


Een andere methode is kopiëren met tar + ssh in plaats van scp:

tar -c -C ./my/local/dir \
  | ssh dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"

29
2017-10-03 18:56



Dit is de beste manier om het te doen. - mttdbrd
Ik kan deze methode niet succesvol laten werken. Zoals geschreven krijg ik sudo: sorry, you must have a tty to run sudo. Als ik "-t" toevoeg om een ​​TTY toe te kennen, dan krijg ik Pseudo-terminal will not be allocated because stdin is not a terminal.. Ik kan dit niet zien werken zonder een wachtwoordloze sudo. - IBBoard
@IBBoard: probeer de oplossing hier ssh -t gebruiken: ssh -t dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www" - Alexander Bird
@AlexanderBird Hoewel dat in veel gevallen werkt, weet ik niet zeker of het hier werkt, omdat we een tarball proberen te pipen via de SSH-verbinding. Zien serverfault.com/questions/14389/... - IBBoard
Dit is wat uiteindelijk voor mij werkte. U hebt geen machtigingen voor een extern bestand dat u naar lokaal wilt kopiëren, doe a sudo tar, archiveer het, wijzig de rechten met behulp van chmod en chownen kopieer het naar lokaal. Vooral als het een map is. - forumulator


Je kan ook gebruiken ansible om dit te bereiken.

Kopiëren naar externe host met Ansible copy module:

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

Ophalen van het gebruik van externe host Ansible fetch module:

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

NOTITIE:

  • De komma in de -i HOST, syntaxis is geen typfout. Het is de manier om ansible te gebruiken zonder een inventarisbestand.
  • -b zorgt ervoor dat de acties op de server als root worden uitgevoerd. -b breidt uit naar --becomeen de standaardinstelling --become-user is root, met de standaard --become-method sudo zijn.
  • flat=yes kopieën net het bestand kopieert niet het hele externe pad naar het bestand
  • Het gebruik van jokertekens in de bestandspaden wordt niet ondersteund door deze niet-module.
  • Een map kopiëren is ondersteund door de copy module, maar niet Door de fetch module.

Specifieke aanroeping voor deze vraag

Hier is een voorbeeld dat specifiek en volledig is gespecificeerd, ervan uitgaande dat de map op uw lokale host met de te distribueren bestanden dat is sourcediren dat de hostnaam van het externe doelwit is hostname:

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

Met de beknopte aanroep als zijnde:

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

P.S., ik realiseer me dat het gezegde "installeer gewoon deze fantastische tool" een beetje een is toon-doof antwoord. Maar ik heb gevonden dat het onmogelijk kan zijn super nuttig voor het beheer van externe servers, dus het installeren van het zal u zeker andere voordelen bieden dan het inzetten van bestanden.


21
2018-02-15 07:03



Ik vind dit antwoord leuk, maar ik raad je aan het te richten op de gestelde vraag versus meer algemene opmerkingen vóór de update. zoiets als ansible -i "hostname," all -u user --become -m copy -a ... - Mike D
@MikeD: hoe zien de bovenstaande wijzigingen eruit? - erik.weathers
beter maar het is mislukt, --module-name is de juiste switchnaam. en sindsdien hostname is de enige host in je inventaris, je kunt het gewoon zeggen all - Mike D
Zou zoiets willen -i 'host,' een geldige syntaxis zijn? Ik denk dat het gemakkelijk is om interpunctie als deze te verliezen bij het lezen van een commando. (Voor de lezer bedoel ik, zo niet de schaal.) - mwfearnley
@mwfearnley: zeker, de shell zal behandelen -i 'host,' en hetzelfde als -i host, of -i "host,". In het algemeen geef ik er de voorkeur aan deze aanroepingen zo kort mogelijk te houden om te voorkomen dat ze angstaanjagend worden, maar je moet het vrij vinden om het zo uitgebreid en expliciet te maken als je denkt dat nodig is voor de duidelijkheid. - erik.weathers


Wanneer je rent sudo su, alle bestanden die u maakt, zullen eigendom zijn van root, maar het is niet mogelijk om standaard rechtstreeks in te loggen als root met ssh of scp. Het is ook niet mogelijk om sudo met scp te gebruiken, dus de bestanden zijn niet bruikbaar. Los dit op door het eigendom van uw bestanden te claimen:

Ervan uitgaande dat uw gebruikersnaam dimitri was, kunt u deze opdracht gebruiken.

sudo chown -R dimitri:dimitri /home/dimitri

Vanaf dat moment, zoals vermeld in andere antwoorden, is de "Ubuntu" manier om sudo te gebruiken, en niet om root-logins. Het is een nuttig paradigma, met grote beveiligingsvoordelen.


12
2017-10-29 23:07



Ik gebruik deze oplossing op elke manier, maar wat als ik volledige toegang tot mijn eigen bestandssysteem zou kunnen krijgen, ik wil niet typen sudo chow ... voor elke afzonderlijke map: S - Dimitris Sapikas
Het wijzigen van het eigendom van alle systeembestanden aan de gebruiker voor het gemak wordt ten zeerste afgeraden. Het zorgt ervoor dat elke bug in de gebruikersruimte die u tegenkomt, de veiligheid van uw systeem ernstig in gevaar kan brengen. Het is veel beter om het eigendom van de bestanden die je moet veranderen of bijwerken door SCP te wijzigen, maar om alle andere elementen te laten die het eigendom zijn van root (zoals het hoort te zijn). Dat gezegd hebbende, de -R in chown vertelt het om het eigendom van die map en alle onderliggende bestanden en mappen op recursieve wijze te veranderen ... zodat je alles kunt doen wat je maar wilt. - Bailey S
hmm ... dat lijkt goed te werken, dank je! sorry ik kan niet upmoten (systeem staat me niet toe om te doen ...) - Dimitris Sapikas


Misschien is de beste manier om te gebruiken rsync (Cygwin/cwRsync in Windows) via SSH?

Bijvoorbeeld om bestanden te uploaden met de eigenaar www-data:

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

In jouw geval, als je root-rechten nodig hebt, zal de opdracht er als volgt uitzien:

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

Zien: scp naar externe server met sudo.


8
2017-11-15 10:14





Als u de OpenSSH-hulpmiddelen gebruikt in plaats van PuTTY, kunt u dit bereiken door de scp bestandsoverdracht op de server met sudo. Zorg ervoor dat je een hebt sshd daemon op uw lokale computer. Met ssh -R u kunt de server een manier geven om contact te maken met uw machine.

Op uw computer:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Naast dat u zich aanmeldt op de server, zal dit elke verbinding die op poort 11111 van de server is gemaakt doorsturen naar de poort 22 van uw machine: de poort die uw sshd luistert naar.

Start de bestandsoverdracht op de server als volgt:

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .

5
2017-11-21 16:52





Snel manier:

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

5
2018-01-16 13:01



Dit antwoord is onderschat. Het is eenvoudig, schoon, leest of schrijft een rootbestand met een enkele atoombewerking en vereist niets dat er niet al zeker van is als je scp gebruikt. Belangrijkste nadeel is dat het geen machtigingen kopieert. Als je dat wilt, is de teeroplossing beter. Dit is een krachtige techniek, vooral in combinatie met xargs / bash magic om paden te doorkruisen .. - markgo2k


Je mag het script gebruiken dat ik geschreven heb, geïnspireerd door dit onderwerp:

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

maar dit vereist wat gekke dingen (wat trouwens is, automatisch gedaan door een script)

  1. server naar welk bestand wordt verzonden, vraagt ​​niet langer om een ​​wachtwoord bij het tot stand brengen van een ssh-verbinding met de broncomputer
  2. vanwege de noodzaak van een gebrek aan sudo prompt op de server, zal sudo voor de gebruiker niet langer om een ​​wachtwoord op de externe machine vragen

Hier gaat het 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

1
2017-11-21 19:47



@Braiam ja, sorry, sorry voor link, het script is best lang en dat was de reden :) - test30


Je kunt ssh, sudo en bijvoorbeeld tar combineren om bestanden tussen servers te verzenden zonder dat je als root kunt inloggen en geen toestemming hebt om de bestanden met je gebruiker te openen. Dit is enigszins onhandig, dus ik heb een script geschreven om dit te helpen. Je kunt het script hier vinden: https://github.com/sigmunau/sudoscp

of hier:

#! / Bin / bash
res = 0
from = $ 1
to = $ 2
verschuiving
verschuiving
files = "$ @"
als test -z "$ van" -o -z "$ naar" -o -z "$ bestanden"
dan
    echo "Gebruik: $ 0 (bestand) *"
    echo "voorbeeld: $ 0 server1 server2 / usr / bin / myapp"
    afslag 1
fi

lees -s-p "Voer wachtwoord in:" sudopassword
echo ""
temp1 = $ (mktemp)
temp2 = $ (mktemp)
(echo "$ sudopassword"; echo "$ sudopassword" | ssh $ from sudo -S tar c-P -C / $ files 2> $ temp1) | ssh $ naar sudo -S tar x -v -P -C / 2 > $ temp2
sourceres = $ {PIPESTATUS [0]}
als [$? -ne 0 -o $ sourceres -ne 0]
dan
    echo "Niet!" > & 2
    echo "$ from output:"> & 2
    cat $ temp1> & 2
    echo ""> & 2
    echo "$ naar uitvoer:"> & 2
    cat $ temp2> & 2
    res = 1
fi

rm $ temp1 $ temp2
exit $ res

1
2017-07-01 15:16



Welkom bij Ask Ubuntu. Zou je het script alsjeblieft in je antwoord kunnen opnemen? Ik weet dat het onwaarschijnlijk is, maar als de github repo ooit is verwijderd of de URL is gewijzigd, is het antwoord ongeldig. Het is beter om het script rechtstreeks op te nemen en de github-repo als bron achter te laten. - Michael Lindman


Hier is een aangepaste versie van het antwoord van Willie Wheeler die de bestanden via tar overdraagt, maar ook ondersteunt het doorgeven van een wachtwoord aan sudo op de externe host.

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

Het beetje extra magie hier is de -S optie voor sudo. Van de sudo man-pagina:

-S, --stdin                    Schrijf de prompt naar de standaardfout en lees het wachtwoord uit de standaardinvoer in plaats van het terminalapparaat te gebruiken. Het wachtwoord moet worden gevolgd door een nieuwlijnteken.

Nu willen we eigenlijk dat de uitvoer van teer in ssh wordt gepulseerd en die de stdin van ssh doorverwijst naar de stdout van teer, en op welke manier dan ook het wachtwoord in sudo van de interactieve terminal verwijdert. (We zouden de ASKPASS-functie van sudo aan de andere kant kunnen gebruiken, maar dat is een ander verhaal.) We kunnen het wachtwoord in sudo krijgen door het van tevoren vast te leggen en het aan de teerversie toe te voegen door deze bewerkingen in een submap uit te voeren en de uitvoer van de subshell in ssh. Dit heeft ook het bijkomende voordeel dat er geen omgevingsvariabele met ons wachtwoord in onze interactieve shell achterblijft.

U zult merken dat ik 'lees' niet heb uitgevoerd met de -p optie om een ​​prompt af te drukken. Dit komt omdat de wachtwoordprompt van sudo gemakkelijk via ssh doorgestuurd wordt naar de stderr van onze interactieve shell. Je vraagt ​​je misschien af ​​"hoe wordt sudo uitgevoerd gezien het binnen de SSH rechts van onze pijp loopt?" Wanneer we meerdere opdrachten uitvoeren en de uitvoer van de ene naar de andere pipen, voert de bovenliggende shell (de interactieve shell in dit geval) elke opdracht uit in de reeks onmiddellijk na het uitvoeren van de vorige. Omdat elk commando achter een pipe wordt uitgevoerd, koppelt de parent-shell de stdout van de linkerzijde aan de stdin van de rechterkant. Uitvoer wordt dan invoer wanneer deze door processen gaat. We kunnen dit in actie zien door de volledige opdracht uit te voeren en de procesgroep (Ctrl-z) te achterhalen voordat we ons wachtwoord typen en vervolgens de procesboom te bekijken.

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

Onze interactieve shell is PID 7168, onze subshell is PID 7969 en ons SSH-proces is PID 7970.

Het enige nadeel is dat lezen invoer accepteert voordat sudo tijd heeft om zijn prompt terug te sturen. Op een snelle verbinding en een snelle externe host zult u dit niet merken, maar u zou het kunnen doen als een van beide langzaam is. Elke vertraging heeft geen invloed op de mogelijkheid om de prompt in te voeren; het kan gewoon verschijnen nadat u bent begonnen met typen.

Opmerking Ik heb eenvoudig een hostbestand voor "remote_Host" toegevoegd aan mijn lokale computer voor de demo.


0
2018-05-06 10:17