Come copio i file che richiedono l'accesso come root con scp?


168

Ho un server Ubuntu al quale mi collego usando SSH.

Devo caricare i file dalla mia macchina /var/www/sul server, i file in /var/www/sono di proprietà di root.

Utilizzando PuTTY, dopo aver effettuato l'accesso, devo digitare sudo sue la mia password per poter modificare i file /var/www/.

Ma quando copio i file usando WinSCP, non riesco a creare / modificare i file /var/www/, perché l'utente con cui mi connetto non ha i permessi sui file /var/www/e non posso dire sudo sucome faccio in caso di una sessione SSH .

Sai come ho potuto affrontare questo?

Se stavo lavorando sul mio computer locale, chiamerei gksudo nautilusma in questo caso ho solo l'accesso terminale al computer.


Sembra più una domanda per il tuo provider di server virtuale o per gli sviluppatori putty o winscp.
dobey,

7
@dobey hai ovviamente torto, si tratta dei privilegi di Ubuntu!
Dimitris Sapikas,

7
Perché è chiuso? Questa è una domanda perfettamente valida sulla copia di file con scp - ogni sviluppatore web ha familiarità con questa situazione
Sergey


Ho un problema simile. Creo un file (HTML in questo caso) su computer Windows e provo a copiarlo con WinSCP nella cartella / var / www / html / website. E dice che c'è un problema di autorizzazione. Perché posso copiare nella mia cartella / home ho copiato il file in due passaggi, ma non è molto comodo :-) Ho provato ad aggiungere il mio utente al gruppo www-data, ma non mi è stato di aiuto. Qualche idea sul perché l'aggiunta all'utente a www-data non permetta ancora all'utente di copiare un file nella cartella di proprietà del gruppo www-data?
JanezKranjski,

Risposte:


126

Hai ragione, non c'è niente sudoquando si lavora con scp. Una soluzione alternativa consiste nell'utilizzare scpper caricare file in una directory in cui l'utente dispone delle autorizzazioni per creare file, quindi accedere tramite ssh e utilizzare sudoper spostare / copiare i file nella destinazione 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

Un'altra soluzione sarebbe quella di modificare le autorizzazioni / la proprietà delle directory in cui si caricano i file, in modo che l'utente non privilegiato sia in grado di scrivere in tali directory.

In generale, lavorare rootnell'account dovrebbe essere un'eccezione, non una regola - il modo in cui formuli la tua domanda mi fa pensare che forse stai abusando un po ', il che a sua volta porta a problemi con le autorizzazioni - in circostanze normali non è necessario privilegi di super amministratore per accedere ai tuoi file.

Tecnicamente, puoi configurare Ubuntu per consentire l'accesso remoto direttamente come root, ma questa funzione è disabilitata per un motivo, quindi ti consiglio vivamente di non farlo.


non ho avuto la prima soluzione, potresti per favore essere un po 'più spesifico?
Dimitris Sapikas,

Quando dico i miei file intendo / var / www, sto usando i miei vps come web server .... nella mia cartella ho pieno accesso
Dimitris Sapikas,

7
Ri. la prima soluzione. 1. scp -R mysite dimitris@myserver.com:/home/dimitris/2. ssh dimitris@myserver.com3. sudo mv ~/mysite /var/www- si tratta di un processo in 2 passaggi, prima di tutto scpi file nella directory home, quindi si accede tramite ssh e si copia / sposta i file dove dovrebbero essere
Sergey,

36

Un altro metodo è copiare usando tar + ssh invece di scp:

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

2
Questo è il modo migliore per farlo.
mttdbrd

2
Non riesco a far funzionare questo metodo con successo. Come scritto capisco sudo: sorry, you must have a tty to run sudo. Se aggiungo "-t" per allocare un TTY, ottengo Pseudo-terminal will not be allocated because stdin is not a terminal.. Non riesco a vederlo funzionare senza sudo senza password.
IBBoard,

1
@IBBoard: prova qui la soluzione usando ssh -t:ssh -t dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
Alexander Bird,

2
@AlexanderBird Anche se funziona in molti casi, non sono sicuro che funzioni qui perché stiamo provando a reindirizzare un tarball sulla connessione SSH. Vedi serverfault.com/questions/14389/…
IBBoard

Questo è ciò che alla fine ha funzionato per me. Non si dispone delle autorizzazioni per un file remoto che si desidera copiare in locale, eseguire un sudo tar, archiviarlo, modificare le autorizzazioni utilizzando chmode chown, quindi copiarlo in locale. Soprattutto se si tratta di una directory.
Forumulator

28

Modo rapido

Dal server al computer locale:

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

Dal computer locale al server:

cat /home/user/file | ssh user@server "sudo tee -a /etc/dir/file"

5
Questa risposta è sottovalutata. È semplice, pulito, legge o scrive un file root con un'unica operazione atomica e non richiede nulla che non sia già garantito se si utilizza scp. Lo svantaggio principale è che non copia le autorizzazioni. Se lo desideri, la soluzione tar è migliore. Questa è una tecnica potente, in particolare se combinata con la magia xargs / bash per attraversare percorsi ..
markgo2k,

Penso che la domanda riguardasse il caricamento di un file da locale a remoto e non viceversa
Korayem,

1
Ben fatto. Questo è esattamente quello che stavo cercando sia su che giù. Grazie
Jeremy,

Merita sicuramente la risposta migliore.
Andrew Watson,

Questo può essere fatto anche per una directory anziché per un file?
lucidbrot,

26

Puoi anche usare ansibleper realizzare questo.

Copia sull'host remoto usando il copymodulo di ansible :

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

Recupera dall'host remoto utilizzando il fetchmodulo di ansible :

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

NOTA:

  • La virgola nella -i HOST,sintassi non è un errore di battitura. È il modo di usare ansible senza bisogno di un file di inventario.
  • -bfa sì che le azioni sul server vengano eseguite come root. -bsi espande in --become, e il valore predefinito --become-userè root, con il valore predefinito --become-methodsudo.
  • flat=yescopia solo il file, non copia l'intero percorso remoto che porta al file
  • L'uso di caratteri jolly nei percorsi dei file non è supportato da questi moduli rispondibili.
  • La copia di una directory è supportata dal copymodulo, ma non dal fetchmodulo.

Invocazione specifica per questa domanda

Ecco un esempio specifico e completamente specificato, supponendo che la directory sul tuo host locale contenente i file da distribuire sia sourcedire che il nome host della destinazione remota sia hostname:

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

Con l'invocazione concisa che è:

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

PS, mi rendo conto che dire "basta installare questo favoloso strumento" è una specie di risposta sorda. Ma ho trovato ansible per essere super utile per l'amministrazione di server remoti, quindi installarlo porterà sicuramente altri vantaggi oltre alla distribuzione dei file.


Mi piace questa risposta, ma ti consiglio di indirizzarla alla domanda posta rispetto a un commento più generalizzato prima di votare. qualcosa del genereansible -i "hostname," all -u user --become -m copy -a ...
Mike D,

@MikeD: come appaiono le modifiche sopra?
erik.weathers,

1
Qualcosa come -i 'host,'una sintassi valida? Penso che sia facile perdere la punteggiatura in questo modo durante la lettura di un comando. (Per il lettore intendo, se non la shell.)
mwfearnley,

1
@mwfearnley: certo, la shell tratterà -i 'host,'e lo stesso di -i host,o -i "host,". In generale, preferisco mantenere queste invocazioni il più brevi possibile per evitare che siano scoraggianti, ma dovresti sentirti libero di renderlo verboso ed esplicito come ritieni necessario per chiarezza.
erik.weathers,

2
Modo di pensare fuori dagli schemi! Grande uso di Ansible
jonatan

12

Quando esegui sudo su, tutti i file che crei saranno di proprietà di root, ma per impostazione predefinita non è possibile accedere direttamente come root con ssh o scp. Inoltre, non è possibile utilizzare sudo con scp, quindi i file non sono utilizzabili. Risolvilo rivendicando la proprietà sui tuoi file:

Supponendo che il tuo nome utente fosse dimitri, puoi usare questo comando.

sudo chown -R dimitri:dimitri /home/dimitri

Da quel momento in poi, come menzionato in altre risposte, il modo "Ubuntu" è usare sudo e non gli accessi root. È un paradigma utile, con grandi vantaggi in termini di sicurezza.


sto usando questa soluzione in ogni modo, ma se potessi avere pieno accesso al mio file system, non voglio digitare sudo chow ...per ogni singola directory: S
Dimitris Sapikas,

2
Cambiare la proprietà di tutti i file di sistema per l'utente per comodità di passaggio è altamente scoraggiato. Consente a qualsiasi bug dello spazio utente che potresti incontrare di compromettere gravemente la sicurezza del tuo sistema. È molto meglio cambiare la proprietà dei file che è necessario modificare o aggiornare da SCP, ma lasciare tutto il resto di proprietà di root (come dovrebbe essere). Detto questo, l' -Rin chowndice di cambiare la proprietà di tale directory, e tutti i file e le directory ricorsivamente i bambini ... in modo da poter fare tutto quello che vuoi.
Trognandro

hmm .... sembra funzionare bene, grazie! scusa non posso votare (il sistema non mi permette di fare ...)
Dimitris Sapikas,

11

Potrebbe essere il modo migliore è usare rsync( Cygwin / cwRsync in Windows) su SSH?

Ad esempio, per caricare file con il proprietario www-data:

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

Nel tuo caso, se hai bisogno dei privilegi di root, il comando sarà così:

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

Vedi: scp sul server remoto con sudo .


5

Se usi gli strumenti OpenSSH invece di PuTTY, puoi farlo avviando il scptrasferimento di file sul server con sudo. Assicurati di avere un sshddemone in esecuzione sul tuo computer locale. Con ssh -Rte puoi dare al server un modo per contattare la tua macchina.

Sulla tua macchina:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Oltre ad accedere al server, questo inoltrerà tutte le connessioni effettuate sulla porta 11111 del server alla porta 22 della macchina: la porta su cui si sshdsta ascoltando.

Sul server, avviare il trasferimento dei file in questo modo:

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

1

Puoi usare lo script che ho scritto ispirandomi a questo argomento:

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

ma questo richiede alcune cose folli (che è tra l'altro fatto automaticamente dallo script)

  1. il server a cui viene inviato il file non chiederà più la password durante la connessione ssh al computer di origine
  2. a causa della necessità di mancanza del prompt sudo sul server, sudo non chiederà più la password sulla macchina remota, per l'utente

Ecco la sceneggiatura:

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

@Braiam sì, certo, scusa per il link, la sceneggiatura è piuttosto lunga e questo è stato il motivo :)
test30

1

È possibile combinare ssh, sudo e ad esempio tar per trasferire file tra server senza essere in grado di accedere come root e non avere il permesso di accedere ai file con l'utente. Questo è un po 'complicato, quindi ho scritto una sceneggiatura per aiutarlo. Puoi trovare lo script qui: https://github.com/sigmunau/sudoscp

o qui:

#! / Bin / bash
res = 0
da = $ 1
a = $ 2
cambio, turno
cambio, turno
file = "$ @"
se test -z "$ da" -o -z "$ a" -o -z "$ file"
poi
    echo "Utilizzo: $ 0 (file) *"
    echo "esempio: $ 0 server1 server2 / usr / bin / myapp"
    uscita 1
fi

read -s -p "Inserisci password:" sudopassword
eco ""
temp1 = $ (mktemp)
temp2 = $ (mktemp)
(echo "$ sudopassword"; echo "$ sudopassword" | ssh $ da sudo -S tar c -P -C / $ files 2> $ temp1) | ssh $ a sudo -S tar x -v -P -C / 2 > $ temp2
sourceres = $ {PIPESTATUS [0]}
se [$? -ne 0 -o $ sourceres -ne 0]
poi
    echo "Fallimento!" > & 2
    echo "$ dall'output:"> & 2
    gatto $ temp1> & 2
    echo ""> & 2
    echo "$ per l'output:"> & 2
    gatto $ temp2> & 2
    res = 1
fi

rm $ temp1 $ temp2
uscire da $ res

Benvenuti in Ask Ubuntu. Potresti includere lo script nella risposta? So che è improbabile, ma se il repository github fosse mai rimosso o l'URL fosse cambiato, la risposta sarebbe nulla. È meglio includere direttamente lo script e lasciare il repository github come fonte.
Michael Lindman,

0

Ecco una versione modificata della risposta di Willie Wheeler che trasferisce i file tramite tar ma supporta anche il passaggio di una password su sudo sull'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\""

Un po 'di magia in più qui è l'opzione -S per sudo. Dalla pagina man sudo:

-S, --stdin Scrive il prompt per l'errore standard e legge la password dall'input standard invece di usare il terminale. La password deve essere seguita da un carattere di nuova riga.

Ora vogliamo effettivamente che l'output di tar sia reindirizzato in ssh e che reindirizzi lo stdin di ssh allo stdout di tar, rimuovendo qualsiasi modo per passare la password in sudo dal terminale interattivo. (Potremmo usare la funzione ASKPASS di sudo sull'estremità remota ma questa è un'altra storia.) Possiamo ottenere la password in sudo anche se catturandola in anticipo e prepagandola sull'output tar eseguendo quelle operazioni in una subshell e eseguendo il piping dell'output di la subshell in ssh. Questo ha anche il vantaggio di non lasciare una variabile d'ambiente contenente la nostra password sospesa nella nostra shell interattiva.

Noterai che non ho eseguito 'read' con l'opzione -p per stampare un prompt. Questo perché la richiesta della password di sudo è convenientemente passata allo standard della nostra shell interattiva tramite ssh. Potresti chiederti "come viene eseguita sudo dato che è in esecuzione all'interno di ssh a destra della nostra pipe?" Quando eseguiamo più comandi e convogliamo l'output di uno nell'altro, la shell padre (la shell interattiva in questo caso) esegue ogni comando nella sequenza immediatamente dopo aver eseguito il precedente. Man mano che ogni comando dietro una pipe viene eseguito, la shell genitrice collega (reindirizza) lo stdout del lato sinistro allo stdin del lato destro. L'output diventa quindi input mentre passa attraverso i processi.

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

La nostra shell interattiva è PID 7168, la nostra subshell è PID 7969 e il nostro processo ssh è PID 7970.

L'unico inconveniente è che read accetterà l'input prima che sudo abbia il tempo di rispedire il prompt. Su una connessione veloce e un host remoto veloce non te ne accorgerai, ma potresti essere lento. Eventuali ritardi non influiranno sulla possibilità di inserire il prompt; potrebbe apparire solo dopo aver iniziato a digitare.

Nota Ho semplicemente aggiunto una voce del file host per "remote_Host" al mio computer locale per la demo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.