Как скопировать файлы, которые требуют доступа root с помощью scp?

139

У меня есть сервер Ubuntu, к которому я подключаюсь, используя SSH.

Мне нужно загрузить файлы с моей машины в /var/www/ на сервере, файлы в /var/www/ принадлежат root .

Используя PuTTY, после входа в систему, я должен сначала набрать sudo su и мой пароль, чтобы иметь возможность изменять файлы в /var/www/ .

Но когда я копирую файлы с помощью WinSCP, я не могу создавать файлы создания / изменения в /var/www/ , потому что пользователь, с которым я подключаюсь, не имеет прав на файлы в /var/www/ , и я не могу сказать sudo su , как и в случае сеанса ssh.

Вы знаете, как я могу справиться с этим?

Если бы я работал на своей локальной машине, я бы назвал gksudo nautilus , но в этом случае у меня есть только терминал доступа к машине.

    
задан Dimitris Sapikas 29.10.2012 в 21:03
источник

10 ответов

106

Вы правы, нет sudo при работе с scp . Обходным путем является использование scp для загрузки файлов в каталог, в котором у пользователя есть разрешения на создание файлов, затем войдите через ssh и используйте sudo для перемещения / копирования файлов в их конечный пункт назначения.

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

Другим решением было бы изменить права доступа / права на каталоги, в которые вы загружаете файлы, поэтому ваш непривилегированный пользователь может писать в эти каталоги.

Как правило, работа в root учетной записи должна быть исключением, а не правилом - как вы формулируете свой вопрос заставляет меня думать, может быть, вы немного злоупотребляете им, что, в свою очередь, приводит к проблемам с разрешениями - при нормальных вам не нужны привилегии супер-администратора для доступа к вашим собственным файлам.

Технически вы можете настроить Ubuntu на разрешение удаленного входа напрямую как root , но эта функция отключена по какой-либо причине, поэтому я настоятельно рекомендую вам не делать этого.

    
ответ дан Sergey 29.10.2012 в 22:22
источник
29

Другим методом является копирование с использованием tar + ssh вместо scp:

tar -c -C ./my/local/dir \
  | ssh dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
    
ответ дан Willie Wheeler 03.10.2014 в 18:56
23

Вы также можете использовать ansible , чтобы выполнить это.

Скопируйте на удаленный хост с помощью модуля copy ansible :

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

Извлечение из удаленного хоста с помощью модуля fetch ansible :

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

Примечание:

  • Запятая в синтаксисе -i HOST, не является опечаткой. Это способ использования без необходимости файла инвентаризации.
  • -b заставляет действия на сервере выполняться как root. -b расширяется до --become , а по умолчанию --become-user является root, при этом по умолчанию --become-method является sudo.
  • flat=yes копирует только файл, не копирует весь удаленный путь, ведущий к файлу
  • Использование подстановочных знаков в пути к файлам не поддерживается этими незаменимыми модулями.
  • Копирование каталога поддерживается модулем copy , но not модулем fetch .

Конкретный вызов для этого вопроса

Вот пример, который является конкретным и полностью указанным, предполагая, что каталог на вашем локальном хосте, содержащий распространяемые файлы, является sourcedir , а имя хоста удаленной цели - hostname :

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

С кратким вызовом:

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

P.S., я понимаю, что высказывание «просто установите этот сказочный инструмент» является своего рода тон-глухой ответ. Но я нашел возможным использовать super для администрирования удаленных серверов, поэтому его установка, несомненно, принесет вам другие преимущества, помимо развертывания файлов.

    
ответ дан erik.weathers 15.02.2016 в 07:03
12

Когда вы запустите sudo su , любые созданные вами файлы будут принадлежать root, но по умолчанию невозможно напрямую войти в систему с правами root с помощью ssh или scp. Также невозможно использовать sudo с scp, поэтому файлы не могут использоваться. Исправьте это, заявив право собственности на ваши файлы:

Предполагая, что ваше имя пользователя было dimitri, вы можете использовать эту команду.

sudo chown -R dimitri:dimitri /home/dimitri

С этого момента, как упоминалось в других ответах, способ «Ubuntu» - использовать sudo, а не root-логины. Это полезная парадигма с большими преимуществами безопасности.

    
ответ дан Bailey S 29.10.2012 в 23:07
8

Может быть, лучше всего использовать rsync ( Cygwin / cwRsync в Windows) через SSH?

Например, чтобы загрузить файлы с владельцем www-data :

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

В вашем случае, если вам нужны привилегии root, команда будет выглядеть так:

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

Смотрите: scp для удаленного сервера с помощью sudo .

    
ответ дан Alexey Vazhnov 15.11.2016 в 10:14
6

Быстрый способ:

ssh user@server "sudo cat /etc/dir/file" > /home/user/file
    
ответ дан Anderson Lira 16.01.2017 в 13:01
5

Если вы используете инструменты OpenSSH вместо PuTTY, вы можете выполнить это, инициировав передачу файла scp на сервере с sudo . Убедитесь, что на вашем локальном компьютере установлен демон sshd . С помощью ssh -R вы можете дать серверу возможность связаться с вашей машиной.

На вашей машине:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

В дополнение к регистрации на сервере, это переадресует каждое соединение, сделанное на порте сервера 11111, на порт 22 вашего компьютера: прослушивает порт, на который ваш sshd .

На сервере запустите передачу файлов следующим образом:

cd /var/www/
sudo scp -P 11111 -r LOCAL_USERNAME@localhost:FOLDERNAME .
    
ответ дан bergoid 21.11.2016 в 16:52
1

Вы можете использовать написанный мной сценарий, вдохновленный этой темой:

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

, но для этого требуются некоторые сумасшедшие вещи (которые автоматически выполняются сценарием)

  1. сервер, файл которого отправляется, больше не будет запрашивать пароль при установлении подключения ssh к исходному компьютеру.
  2. из-за необходимости в отсутствии приглашения sudo на сервере, sudo больше не будет запрашивать пароль на удаленной машине, для пользователя

Вот сценарий:

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
    
ответ дан test30 21.11.2013 в 19:47
1

Вы можете комбинировать ssh, sudo и eg tar для передачи файлов между серверами без возможности входа в систему с правами администратора и не имеющих доступа к файлам с вашим пользователем. Это немного затруднительно, поэтому я написал сценарий, чтобы помочь этому. Здесь вы можете найти скрипт: Ссылка

или здесь:

#! /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
    
ответ дан sigmunda 01.07.2015 в 15:16
0

Вот модифицированная версия ответа Вилли Уилера, которая передает файл (ы) через tar, но также поддерживает передачу пароля на sudo на удаленном хосте.

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

Немного лишней магии здесь -S вариант sudo. На странице sudo man:

-S, --stdin Write the prompt to the standard error and read the password from the standard input instead of using the terminal device. The password must be followed by a newline character.

Теперь мы действительно хотим, чтобы вывод tar был передан в ssh, и он перенаправляет stdin ssh на stdout tar, удаляя любой способ передать пароль в sudo из интерактивного терминала. (Мы можем использовать функцию ASKPASS от sudo на удаленном конце, но это еще одна история.) Мы можем получить пароль в sudo, хотя, предварительно захватив его и добавив его в выход tar, выполнив эти операции в подоболочке и выполнив вывод подоболочка в ssh. Это также имеет дополнительное преимущество, не оставляя переменную среды, содержащую наш пароль, свисающий в нашей интерактивной оболочке.

Вы заметите, что я не выполнил 'read' с параметром -p для печати приглашения. Это связано с тем, что запрос пароля от sudo удобно передавать обратно в stderr нашей интерактивной оболочки через ssh. Вы можете задаться вопросом: «Как выполняется sudo, поскольку он работает внутри ssh справа от нашей трубы?» Когда мы выполняем несколько команд и обрабатываем вывод одного в другое, родительская оболочка (в этом случае интерактивная оболочка) выполняет каждую команду в последовательности сразу после выполнения предыдущего. Поскольку каждая команда за трубой выполняется, родительская оболочка присоединяет (перенаправляет) stdout левой стороны к stdin правой части. Выход затем становится входным, когда он проходит через процессы. Мы можем увидеть это в действии, выполнив всю команду и опираясь на группу процессов (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"'

Наша интерактивная оболочка PID 7168, наша подоболочка - PID 7969, а наш процесс ssh - PID 7970.

Единственный недостаток заключается в том, что чтение будет принимать входные данные до того, как sudo успеет отправить обратно приглашение. При быстром подключении и быстром удалённом хосте вы не заметите этого, но можете, если он медленный. Любая задержка не повлияет на возможность ввода подсказки; это может появиться после того, как вы начали печатать.

Примечание. Я просто добавил запись файла хоста для «remote_Host» на свой локальный компьютер для демонстрации.

    
ответ дан Bruce 06.05.2017 в 10:17

Ознакомьтесь с другими вопросами по меткам