Jak mohu kopírovat soubory, které potřebují root s scp?

137

Mám server Ubuntu, ke kterému se připojuji pomocí SSH.

Potřebuji nahrát soubory ze svého počítače na/var/www/ na serveru, soubory/var/www/ jsou vlastněnyroot.

Při použití protokolu PuTTY se po přihlášení musím nejprve zapsatsudo su a heslo, aby bylo možné upravit soubory v/var/www/.

Ale když kopíruji soubory pomocí WinSCP, nemohu vytvořit soubory pro vytváření / úpravy v/var/www/, protože uživatel, se kterým se připojuji, nemá oprávnění k souborům v/var/www/ a nemohu říci sudo su jako já v případě relace ssh.

Víte, jak bych s tím mohl vyřešit?

Kdybych pracoval na svém místním počítači, zavolal bychgksudo nautilus, ale v tomto případě mám jen terminálový přístup ke stroji.

    
dané Dimitris Sapikas 29.10.2012 22:03

10 odpovědí

106

Máte pravdu, při práci ssudo neexistujescp. Řešením je použítscp k nahrání souborů do adresáře, kde má váš uživatel oprávnění k vytváření souborů, poté se přihlásit přes ssh a použítsudo k přesunutí / kopírování souborů do konečného cíle.

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

Dalším řešením by bylo změnit oprávnění / vlastnictví adresářů, na které nahráváte soubory, takže váš neoprávněný uživatel je schopen napsat do těchto adresářů.

Obecně platí, že práce v účturoot by měla být výjimkou, nikoliv pravidlem - způsob, jakým formulujete svou otázku, mě přemýšlí, že možná trochu zneužíváte, což zase vede k problémům s oprávněním - okolnosti nepotřebujete privilegia super admin pro přístup k vašim vlastním souborům.

Z technického hlediska můžete nakonfigurovat Ubuntu tak, aby umožňovalo vzdálené přihlášení přímo jakoroot, ale tato funkce je z nějakého důvodu zakázána, takže bych vám rád odporoval proti tomu.

    
odpověděl Sergey 29.10.2012 23:22
29

Další metodou je kopírovat pomocí tar + ssh namísto scp:

tar -c -C ./my/local/dir \
  | ssh dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
    
odpověděl Willie Wheeler 03.10.2014 20:56
23

Pro dosažení tohoto cíle můžete také použítansible.

Kopírování do vzdáleného hostitele pomocí modulucopy :

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

Načíst ze vzdáleného hostitele pomocí modulufetch :

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

POZNÁMKA:

  • Čárka v syntaxi-i HOST, není překlep. Je to způsob, jak lze použít bez nutnosti souboru inventáře.
  • -b způsobuje, že akce na serveru budou provedeny jako root. -b se rozšiřuje na--become a výchozí--become-user je kořen, výchozí--become-method je sudo.
  • flat=yes kopie jen soubor nekopíruje celou vzdálenou cestu vedoucí do souboru
  • Použití zástupných znaků v cestách souborů není podporováno těmito moduly.
  • Kopírování adresáře je podporováno modulemcopy, ale ne modulemfetch.

Konkrétní vyvolání této otázky

Zde je příklad, který je specifický a plně specifikovaný, za předpokladu, že adresář na vašem místním hostiteli, který obsahuje distribuované soubory, jesourcedir a název hostitele vzdáleného cíle jehostname:

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

Stručné vyvolání je:

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

P.S., uvědomuji si, že říkat "stačí nainstalovat tento báječný nástroj" je trochu a tón-hluchá odpověď. Naladil jsem se, že je super užitečný pro správu vzdálených serverů, takže instalace jistě vám přinese další výhody za nasazením souborů.

    
odpověděl erik.weathers 15.02.2016 08:03
12

Pokud spustítesudo su, všechny soubory, které vytvoříte, budou vlastněny kořenem, ale ve výchozím nastavení není možné přímo přihlásit jako root s ssh nebo scp. Rovněž není možné použít sudo s scp, takže soubory nejsou použitelné. Opravte to tím, že si vyžádáte vlastnictví souborů:

Za předpokladu, že vaše uživatelské jméno bylo dimitri, můžete použít tento příkaz.

sudo chown -R dimitri:dimitri /home/dimitri

Od té doby, jak je uvedeno v jiných zprávách, je cesta "Ubuntu" používána jako sudo a nikoliv při přihlašování do kořenového adresáře. Je to užitečná paradigma s velkými bezpečnostními výhodami.

    
odpověděl Bailey S 30.10.2012 00:07
8

Může být nejlepším způsobem, jak použít systém% s_cde% ( Cygwin / cwRsync v systému Windows)

Chcete-li například nahrát soubory s vlastníkemrsync:

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

V případě, že potřebujete root oprávnění, příkaz bude takto:

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

Viz: scp na vzdálený server se sudo .

    
odpověděl Alexey Vazhnov 15.11.2016 11:14
6

Rychlý způsob:

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

Používáte-li namísto PuTTY nástroje OpenSSH, můžete to provést inicializací přenosu souborůscp na serveru ssudo. Ujistěte se, že na místním počítači běží démonsshd. Pomocíssh -R můžete dát serveru způsob, jak kontaktovat vaše zařízení.

Na vašem počítači:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Kromě přihlášení k serveru se bude přesměrovat každé připojení na portu 11111 serveru na port 22 vašeho počítače: port, který vašesshd naslouchá.

Na serveru spusťte přenos souborů takto:

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

Můžete použít skript, který jsem napsal inspirovaný tímto tématem:

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

ale to vyžaduje nějaké bláznivé věci (což je btw. automaticky provedeno skriptem)

  1. server, do kterého je odeslán soubor, již nebude požadovat heslo při vytváření ssh připojení ke zdrojovému počítači
  2. kvůli nezbytnosti nedostatečného příkazu sudo na serveru, sudo už nebude žádat o heslo na vzdáleném počítači, pro uživatele

Následuje skript:

interface=wlan0
if [[ $# -ge 3 ]]; then interface=; 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: %pr_dfe% local_filename [username@](ip|host):(remote_folder/|remote_filename) [optionalInterface=wlan0]"
echo -e "Example: \n\ttouch /tmp/justtest &&\n\t %pr_dfe% /tmp/justtest remoteuser@ssh.superserver.com:/tmp/ "
exit 1
fi

localFilePath=

test -e $localFilePath 

destString=
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
    
odpověděl test30 21.11.2013 20:47
1

Můžete kombinovat ssh, sudo a např. tar pro přenos souborů mezi servery, aniž byste se mohli přihlásit jako root a nemají oprávnění k přístupu k souborům s vaším uživatelem. To je trochu fiddly, takže jsem napsal skript, který vám pomůže. Zde najdete skript: Odkaz

nebo zde:

#! /bin/bash
res=0
from=
to=
shift
shift
files="$@"
if test -z "$from" -o -z "$to" -o -z "$files"
then
    echo "Usage: %pr_dfe%    (file)*"
    echo "example: %pr_dfe% 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
    
odpověděl sigmunda 01.07.2015 17:16
0

Zde je upravená verze odpovědi Willieho Wheelera, která přenáší soubory přes tar, ale také podporuje předání hesla na sudo na vzdáleném hostiteli.

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

Trochu extra kouzla je volba -S na sudo. Z stránky mana sudo:

  

-S, -stdin                    Zadejte výzvu k standardní chybě a přečtěte si heslo ze standardního vstupu namísto použití terminálového zařízení. Heslo musí být následováno znakem nové linky.

Nyní chceme, aby výstup z tar byl přiveden do ssh a přesměrovával stdin ssh na stdout tar a odstranil jakýkoliv způsob, jak předat heslo do sudo z interaktivního terminálu. (Mohli bychom použít sudoku ASKPASS funkci na vzdáleném konci, ale to je další příběh.) Můžeme dostat heslo do sudo ačkoli zachytit to předem a prepending to na výrobu dehtu tím, že provádí tyto operace v podšálek a potrubí výstupu subshell do ssh. To má také výhodu, že neopustíme proměnnou prostředí, která by obsahovala naše heslo, které se v našem interaktivním prostředí vyskytuje.

Všimnete si, že jsem nevypracoval 'číst' volbou -p a vytiskl výzvu. Je to proto, že výzva k zadání hesla od sudo je pohodlně předána zpět na stderr našeho interaktivního shellu přes ssh. Možná byste se zajímalo, jak je sudo spouštět, protože běží uvnitř ssh napravo od naší trubky? " Když spustíme více příkazů a vytvoříme výstup jednoho do druhého, rodičovský shell (v tomto případě interaktivní shell) provede každý příkaz v pořadí bezprostředně po provedení předchozího. Jakmile je proveden každý příkaz za trubkou, rodičovská skořepina připojí (přesměruje) stdout na levé straně ke stdin pravé strany. Výstup se pak stává vstupem při procházení procesy. Toto můžeme vidět v akci tím, že před zadáním našeho hesla a následným prohlížením stromu procesů provedeme celý příkaz a založíme skupinu procesů (Ctrl-z).

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

Naše interaktivní shell je PID 7168, naše subshell je PID 7969 a náš proces ssh je PID 7970.

Jedinou nevýhodou je to, že čtení bude přijímat vstup předtím, než sudo bude mít čas na odeslání zpět. Při rychlém připojení a rychlém vzdáleném hostiteli to nezaznamenáte, ale pokud je někdy pomalé, můžete to udělat. Jakékoli zpoždění nebude mít vliv na možnost zadat výzvu; může se zobrazit po spuštění psaní.

Všimněte si, že pro demo jsem jednoduše přidal položku hostitelského souboru pro "remote_Host" na svůj počítač.

    
odpověděl Bruce 06.05.2017 12:17