Jak skopiować pliki wymagające uprawnień roota za pomocą scp?

140

Mam serwer Ubuntu, z którym łączę się za pomocą SSH.

Muszę przesłać pliki z mojego komputera do /var/www/ na serwerze, pliki w /var/www/ są własnością root .

Używając PuTTY, po zalogowaniu się muszę najpierw wpisać sudo su i moje hasło, aby móc modyfikować pliki w /var/www/ .

Ale gdy kopiuję pliki przy użyciu WinSCP, nie mogę tworzyć / modyfikować plików w /var/www/ , ponieważ użytkownik, z którym się łączę, nie ma uprawnień do plików w /var/www/ i nie mogę powiedzieć sudo su tak jak w przypadku sesji ssh.

Czy wiesz, jak sobie z tym poradzić?

Gdybym pracował na moim lokalnym komputerze, zadzwoniłbym do gksudo nautilus , ale w tym przypadku mam tylko dostęp do terminala do maszyny.

    
zadawane Dimitris Sapikas 29.10.2012, 22:03
źródło

10 odpowiedzi

106

Masz rację, nie ma sudo podczas pracy z scp . Obejście problemu polega na użyciu scp do przesłania plików do katalogu, w którym użytkownik ma uprawnienia do tworzenia plików, a następnie zaloguj się przez ssh i użyj sudo , aby przenieść / skopiować pliki do miejsca docelowego.

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

Innym rozwiązaniem byłoby zmiana uprawnień / własności katalogów, do których przesyłasz pliki, aby Twój nieuprzywilejowany użytkownik mógł pisać do tych katalogów.

Generalnie, praca na koncie root powinna być wyjątkiem, a nie regułą - sposób, w jaki wypowiadasz swoje pytanie, sprawia, że myślę, że nadużywasz go trochę, co z kolei prowadzi do problemów z uprawnieniami - w normalnych warunkach okoliczności, w których nie potrzebujesz uprawnień superadministratora, aby uzyskać dostęp do własnych plików.

Technicznie, możesz skonfigurować Ubuntu tak, aby zezwalał na zdalne logowanie bezpośrednio jako root , ale ta funkcja jest wyłączona z jakiegoś powodu, więc zdecydowanie zaleciłbym ci tego.

    
odpowiedział Sergey 29.10.2012, 23:22
źródło
29

Inną metodą jest skopiowanie za pomocą tar + ssh zamiast scp:

tar -c -C ./my/local/dir \
  | ssh dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
    
odpowiedział Willie Wheeler 03.10.2014, 20:56
źródło
23

Możesz również użyć ansible , aby to osiągnąć.

Skopiuj do zdalnego hosta za pomocą modułu% ans_de% ansible:

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

Pobierz ze zdalnego hosta za pomocą modułu% ans_de% ansible:

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

UWAGA:

  • Przecinek w składni copy nie jest literówką. Jest to sposób korzystania z ansibli bez potrzeby posiadania pliku inwentaryzacji.
  • fetch powoduje, że akcje na serwerze są wykonywane jako root. -i HOST, rozwija się do -b , a domyślny -b to root, a domyślny --become to sudo.
  • --become-user kopiuje tylko plik, nie kopiuje całej ścieżki zdalnej prowadzącej do pliku
  • Używanie symboli wieloznacznych w ścieżkach plików nie jest obsługiwane przez te moduły ansibli.
  • Kopiowanie katalogu jest obsługiwane przez moduł --become-method , ale nie przez moduł flat=yes .

Swoiste wywołanie dla tego pytania

Oto przykład, który jest specyficzny i w pełni określony, zakładając, że katalog na twoim lokalnym hoście zawiera pliki, które mają być dystrybuowane, jest copy , a nazwa hosta zdalnego jest fetch :

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

Przy zwartym wywołaniu:

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

P.S. Zdaję sobie sprawę, że powiedzenie "po prostu zainstaluj to wspaniałe narzędzie" jest czymś w rodzaju odpowiedź głuchoniemych. Ale znalazłem ansibry super przydatne do administrowania zdalnymi serwerami, więc instalacja z pewnością przyniesie ci inne korzyści poza wdrażaniem plików.

    
odpowiedział erik.weathers 15.02.2016, 08:03
źródło
12

Gdy uruchomisz sudo su , wszystkie tworzone pliki będą własnością root'a, ale domyślnie nie jest możliwe bezpośrednie zalogowanie się jako root przy pomocy ssh lub scp. Nie można również używać sudo z scp, więc pliki nie są użyteczne. Napraw to, zgłaszając prawa własności do swoich plików:

Zakładając, że nazwa użytkownika to dimitri, możesz użyć tego polecenia.

sudo chown -R dimitri:dimitri /home/dimitri

Odtąd, jak wspomniano w innych odpowiedziach, sposobem "Ubuntu" jest używanie sudo, a nie root logowania. Jest to przydatny paradygmat, z dużymi zaletami bezpieczeństwa.

    
odpowiedział trognanders 30.10.2012, 00:07
źródło
8

Może najlepiej używać rsync ( Cygwin / cwRsync w systemie Windows) zamiast SSH?

Na przykład, aby przesłać pliki z właścicielem www-data :

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

W twoim przypadku, jeśli potrzebujesz uprawnień roota, polecenie będzie wyglądało tak:

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

Zobacz: przejdź do zdalnego serwera za pomocą sudo .

    
odpowiedział Alexey Vazhnov 15.11.2016, 11:14
źródło
7

Szybko:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file
    
odpowiedział Anderson Lira 16.01.2017, 14:01
źródło
5

Jeśli używasz narzędzi OpenSSH zamiast PuTTY, możesz to zrobić, inicjując transfer plików scp na serwerze z sudo . Upewnij się, że masz demona sshd działającego na twoim komputerze lokalnym. Dzięki ssh -R możesz dać serwerowi możliwość skontaktowania się z twoim komputerem.

Na komputerze:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Oprócz zalogowania użytkownika na serwerze, każde połączenie wykonane na porcie 11111 serwera zostanie przekazane do portu 22 twojego komputera: port, którego słuchasz sshd .

Na serwerze uruchom przesyłanie plików w następujący sposób:

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .
    
odpowiedział bergoid 21.11.2016, 17:52
źródło
1

Możesz wykorzystać napisany przeze mnie skrypt inspirowany tym tematem:

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

ale wymaga to szalonych rzeczy (co jest btw. automatycznie wykonywane przez skrypt)

  1. serwer, do którego wysyłany jest plik, nie będzie już pytał o hasło podczas nawiązywania połączenia ssh z komputerem źródłowym
  2. ze względu na konieczność braku polecenia sudo na serwerze, sudo nie będzie już pytać o hasło na zdalnym komputerze, dla użytkownika

Oto skrypt:

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
    
odpowiedział test30 21.11.2013, 20:47
źródło
1

Można łączyć ssh, sudo i np. tar w celu przesyłania plików między serwerami bez możliwości zalogowania się jako root i braku uprawnień dostępu do plików z użytkownikiem. Jest to lekko skrzypiące, więc napisałem skrypt, aby pomóc w tym. Skrypt można znaleźć tutaj: link

lub tutaj:

#! /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
    
odpowiedział sigmunda 01.07.2015, 17:16
źródło
0

Oto zmodyfikowana wersja odpowiedzi Willie Wheelera, która przenosi plik (y) za pośrednictwem tar, ale także obsługuje przekazywanie hasła do sudo na zdalnym hoście.

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

Ta odrobina dodatkowej magii to opcja -S do sudo. Ze strony sudo man:

% bl0ck_qu0te%

Teraz faktycznie chcemy, aby wyjście tar'a było przesyłane do ssh i przekierowuje stdin ssh do stdout tar, usuwając jakikolwiek sposób przekazania hasła do sudo z terminalu interaktywnego. (Moglibyśmy użyć funkcji ASKPASS sudo na zdalnym końcu, ale to już inna historia.) Możemy jednak wprowadzić hasło do sudo, przechwytując je z wyprzedzeniem i poprzedzając je wyjściem tar, wykonując te operacje w podpowłoce i wyprowadzając wyjście z podpowłodzenie do ssh. Ma to tę dodatkową zaletę, że nie pozostawiamy zmiennej środowiskowej zawierającej nasze hasło zwisające w naszej interaktywnej powłoce.

Zauważysz, że nie wykonałem "odczytu" za pomocą opcji -p, aby wydrukować monit. Jest tak dlatego, że prośba o podanie hasła z sudo jest wygodnie przekazywana z powrotem do stderr naszej interaktywnej powłoki przez ssh. Możesz się zastanawiać "w jaki sposób wykonuje się sudo, biorąc pod uwagę, że działa on w ssh po prawej stronie naszej rury?" Kiedy wykonujemy wiele komend i wyprowadzamy wyjście jednego do drugiego, wówczas rodzicielska powłoka (w tym przypadku interaktywna powłoka) wykonuje każde polecenie w sekwencji bezpośrednio po wykonaniu poprzedniego. Ponieważ każde polecenie za potokiem jest wykonywane, powłoka macierzysta dołącza (przekierowuje) stdout z lewej strony do stdin po prawej stronie. Wyjście staje się wtedy wejściem, gdy przechodzi przez procesy. Możemy to zobaczyć w akcji, wykonując całą komendę i przygotowując grupę procesów (Ctrl-z) przed wpisaniem hasła, a następnie przeglądając drzewo procesu.

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

Nasza interaktywna powłoka to PID 7168, naszą podpowłoką jest PID 7969, a naszym procesem ssh jest PID 7970.

Jedyną wadą jest to, że read przyjmie dane wejściowe, zanim sudo zdąży wysłać odpowiedź. Na szybkim połączeniu i szybkim zdalnym hoście nie zauważysz tego, ale możesz, jeśli któryś z nich jest wolny. Jakiekolwiek opóźnienie nie wpłynie na możliwość wprowadzenia zachęty; może się pojawić po rozpoczęciu pisania.

Uwaga Po prostu dodałem wpis pliku hosta dla "remote_Host" do mojej maszyny lokalnej dla wersji demonstracyjnej.

    
odpowiedział Bruce 06.05.2017, 12:17
źródło

Przeczytaj inne pytania na temat tagów