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

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

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

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

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

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

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

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

scp -r folder/ user@server.tld:/some/folder/you/dont/need/sudossh 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, но эта функция отключена по какой-то причине, поэтому я бы настоятельно не советовал вам этого делать.

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

С сервера на локальную машину:

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

С локального компьютера на сервер:

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

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

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

Вы также можете использовать ansible для достижения этой цели.

Копирование на удаленный хост с помощью ансибль copy модуль:

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

Выборка с удаленного хоста с помощью ансибль fetch модуль:

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

записка:

  • Запятая в -i HOST, синтаксис - это не опечатка. Это способ использовать ansible без необходимости в файле инвентаризации.
  • -b заставляет действия на сервере выполняться от имени пользователя root. -b расширяется до --become, и значение по умолчанию --become-user является root, с настройкой по умолчанию --become-method быть судо.
  • flat=yes копии просто файл, не копирует весь удаленный путь, ведущий к файлу
  • Использование подстановочных знаков в путях к файлам не поддерживается этими модулями ansible.
  • Копирование каталога является при поддержке copy модуль, но нет посредством 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. Я понимаю, что сказать "просто установите этот потрясающий инструмент" - это своего рода искупительный глухой ответ. Но я обнаружил, что ансибль - это супер полезно для администрирования удаленных серверов, поэтому его установка, несомненно, принесет вам другие преимущества, помимо развертывания файлов.

Может быть, лучший способ - использовать 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

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

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

Видеть: scp на удаленный сервер с помощью sudo.

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

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

sudo chown -R dimitri:dimitri /home/dimitri

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

Если вы используете инструменты 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 .

Вот модифицированная версия ответа Вилли Уилера, которая передает файлы через 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:

-S, --stdin Запишите запрос на стандартную ошибку и считайте пароль со стандартного ввода вместо использования терминального устройства. За паролем должен следовать символ новой строки.

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

Вы заметите, что я не выполнил "чтение" с параметром -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.

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

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

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

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

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

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

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

interface=wlan0if [[ $# -ge 3 ]]; then interface=$3; fithisIP=$(ifconfig | grep $interface -b1 | tail -n1 | egrep -o '[0-9.]{4,}' -m1 | head -n 1)thisUser=$(whoami)localFilePath=/tmp/justfortestdestIP=192.168.0.2destUser=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 1filocalFilePath=$1test -e $localFilePath destString=$2usernameAndHost=$(echo $destString | cut -f1 -d':')if [[ "$usernameAndHost" == *"@"* ]]; thendestUser=$(echo $usernameAndHost | cut -f1 -d'@')destIP=$(echo $usernameAndHost | cut -f2 -d'@')elsedestIP=$usernameAndHostdestUser=$thisUserfidestFolderOnRemoteMachine=$(echo $destString | cut -f2 -d':')set -e #stop script if there is even single errorecho '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; thenecho $key >> ~/.ssh/authorized_keysecho 'Added key to authorized hosts'elseecho "Key already exists in authorized keys"fiecho "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'readecho 'change 'echo '    %sudo   ALL=(ALL:ALL) ALL'echo 'to'echo '    %sudo   ALL=(ALL:ALL) NOPASSWD: ALL'echo "After this step you will be done."readlistOfFiles=$(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"; fielseecho "something went wrong with executing sudo on remote host, failure"fiENDOFSCRIPT) | sudo tee /usr/bin/scpassudo && chmod +x /usr/bin/scpassudo

Вы можете комбинировать ssh, sudo и, например, tar для передачи файлов между серверами, не имея возможности войти в систему с правами root и не имея разрешения на доступ к файлам с вашим пользователем. Это немного неудобно, поэтому я написал сценарий, чтобы помочь этому. Вы можете найти сценарий здесь: https://github.com/sigmunau/sudoscp

или здесь:

>>>>>>>>#! /bin/bashres=0from=$1to=$2shiftshiftfiles="$@"если test -z "$от" -o -z "$до" -o -z "$files"тогда echo "Использование: $0 (файл)*пример "echo ": $0 server1 server2 /usr/bin/myapp" выход 1firead -s -p "Введите пароль: "sudopasswordecho ""temp1=$(mktemp)temp2=$(mktemp)(echo "$sudopassword";echo "$sudopassword"|ssh $из sudo -S / c -P -C / $files 2$temp1)|ssh $для sudo -S / x -v -P -C / 2$temp2sourceres=${PIPESTATUS[0]}если [ $? -ne 0 -o $sourceres -ne 0 ]затем повторите "Сбой!" &2 echo "$с вывода: " &2 cat $temp1 &2 echo "" &2 echo "$на вывод: " &2 cat $temp2 &2 res=1firm $temp1 $temp2exit $рез

Почему это закрыто? Это вполне обоснованный вопрос о копировании файлов с помощью scp - каждый веб-разработчик знаком с этой ситуацией

@dobey вы явно ошибаетесь, речь идет о привилегиях ubuntu !

Это больше похоже на вопрос к вашему поставщику виртуальных серверов или к разработчикам putty или winscp.

Копирование защищенных файлов между серверами в одну строку? должно помочь.

У меня похожая проблема. Я создаю файл (в данном случае HTML) на компьютере с Windows и пытаюсь скопировать его с помощью WinSCP в папку /var/www/html/website. И это говорит о том, что существует проблема с разрешением. Поскольку я могу скопировать в свою / домашнюю папку, я скопировал файл в два этапа, но это не очень удобно :slight_smile: Я попытался добавить своего пользователя в группу www-data, но это не помогло. Есть идеи, почему добавление пользователя в www-data по-прежнему не позволяет пользователю копировать файл в папку, принадлежащую группе www-data?