Kök erişimi gerektiren dosyaları scp ile nasıl kopyalarım?


167

SSH kullanarak bağlandığım bir Ubuntu sunucum var.

Dosyaları makinemden /var/www/sunucuya yüklemem gerekiyor , içindeki dosyalar /var/www/ait root.

PuTTY kullanarak, oturum açtıktan sonra, sudo sudosyaları değiştirebilmek için önce yazmam ve şifremi yazmam gerekiyor /var/www/.

Ancak WinSCP kullanarak dosya kopyalarken, /var/www/bağlanacağım kullanıcının dosyalarda izinleri olmadığı /var/www/ve sudo sussh oturumu durumunda yaptığım gibi söyleyemeyeceğim için dosya oluşturamıyorum / değiştiremiyorum. .

Bununla nasıl başa çıkabileceğimi biliyor musun?

Yerel makinem üzerinde çalışıyor olsaydım arardım gksudo nautilusama bu durumda sadece makineye terminal erişimine sahip oldum.


Bu, sanal sunucu sağlayıcınız veya macun veya winscp geliştiricileri için bir soru gibi görünüyor.
dobey

7
@dobey haksız yere yanlış, bu ubuntu ayrıcalıkları hakkında!
Dimitris Sapikas 30:12

7
Bu neden kapalı? Bu, scp ile dosyaları kopyalamakla ilgili tamamen geçerli bir sorudur - her web geliştiricisi bu duruma aşinadır
Sergey


Benim de benzer bir problemim var. Windows bilgisayarda bir dosya oluşturuyorum (bu durumda HTML) ve WinSCP ile / var / www / html / website klasörüne kopyalamayı deniyorum. Ve bir izin sorunu olduğunu söylüyor. / Home klasörüme kopyalayabildiğim için dosyayı iki adımda kopyaladım, ama çok uygun değil :-) Kullanıcımı www-data grubuna eklemeye çalıştım, ancak yardımcı olmadı. Kullanıcıya www-data'ya eklenmesinin neden bir dosyayı www-data grubuna ait bir klasöre kopyalamasına izin vermediği hakkında bir fikriniz var mı?
JanezKranjski

Yanıtlar:


125

Haklısın, birlikte sudoçalışırken yok scp. Çözüm, scpkullanıcılarınızın dosya oluşturma izinlerinin bulunduğu bir dizine dosya yüklemek, ardından ssh aracılığıyla oturum açmak ve sudodosyaları nihai hedeflerine taşımak / kopyalamak için kullanmaktır .

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

Başka bir çözüm, dosyaları yüklediğiniz dizinlerin izinlerini / sahipliğini değiştirmek, bu nedenle ayrıcalıklı olmayan kullanıcınız bu dizinlere yazabilmektir.

Genel olarak, roothesapta çalışmak bir istisna olmalı, kural değil - sorunuzu ifade etme şekliniz beni biraz kötüye kullandığınızı düşündürüyor, ki bu da normal şartlar altında ihtiyacınız olmayan izinlerle ilgili sorunlara neden oluyor Süper admin ayrıcalıkları kendi dosyalarına erişmek

Teknik olarak, Ubuntu'yu doğrudan oturum açmaya doğrudan izin verecek şekilde yapılandırabilirsiniz root, ancak bu özellik bir nedenle devre dışı bırakıldı, bu nedenle bunu yapmamanız için şiddetle tavsiye ediyorum.


ilk çözümü anlamadım, lütfen daha spesifik bir litle olur musun?
Dimitris Sapikas 30:12

"Diyelim ki kendi dosyalarımı kastediyorum / var / www, vps'imi web sunucusu olarak kullanıyorum .... kendi klasörümde tam erişime sahibim
Dimitris Sapikas

7
Yeniden. ilk çözüm. 1. scp -R mysite dimitris@myserver.com:/home/dimitris/2. ssh dimitris@myserver.com3. sudo mv ~/mysite /var/www- Bu 2 adımlı bir işlemdir, önce scpdosyaları ana dizininize yönlendirin, daha sonra ssh ile giriş yapın ve dosyaları olması gerektiği yere kopyalayın / taşıyın
Sergey

36

Başka bir yöntem scp yerine tar + ssh kullanarak kopyalamaktır:

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

2
Bunu yapmanın en iyi yolu bu.
mttdbrd

2
Bu yöntemin başarıyla çalışmasını sağlayamıyorum. Yazılı olarak alıyorum sudo: sorry, you must have a tty to run sudo. Bir TTY tahsis etmek için "-t" eklersem o zaman alırım Pseudo-terminal will not be allocated because stdin is not a terminal.. Parolasız sudo olmadan bu çalışmayı göremiyorum.
IBBoard

1
@IBBoard: ssh -t kullanarak çözümü burada deneyin :ssh -t dimitris@myserver.com "sudo tar -x --no-same-owner -C /var/www"
Alexander Bird,

2
@AlexanderBird Bu, çoğu durumda çalışırken, burada çalıştığından emin değilim çünkü SSH bağlantısı üzerinden bir tarball atmaya çalışıyoruz. Bkz serverfault.com/questions/14389/...
IBBoard

Bu benim için nihayet çalıştı. Sen bir yapın yerel kopyalamak istediğiniz uzak dosyaya izniniz yok sudo tarkullanılarak, arşivlemek, değişim izinleri chmodve chownve sonra yerel kopyalayın. Özellikle de bir dizinse.
forumulator

27

Hızlı yol

Sunucudan yerel makineye:

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

Yerel makineden sunucuya:

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

5
Bu cevabı çok az. Basit, temiz, tek bir atomik işlem içeren bir kök dosyasını okuyor veya yazıyor ve eğer scp kullanıyorsanız, orada bulunmayı garanti etmeyen hiçbir şey gerektirmiyor. En büyük dezavantajı izinleri kopyalamamasıdır. Bunu istiyorsanız, katran çözümü daha iyidir. Bu güçlü bir tekniktir, özellikle de yolları geçmek için xargs / bash magic ile kombine
edilmişse

Sanırım soru yerelden uzaktaki bir dosyaya yükleme
yapmaktı,

1
Çok güzel yapılmış. Bu tam olarak yukarı ve aşağı aradığım şeydi. Teşekkür ederim
Jeremy

Elbette en iyi cevap olmayı hak ediyor.
Andrew Watson,

Bu bir dosya yerine bir dizin için de yapılabilir mi?
lucidbrot

26

Bunu ansiblebaşarmak için de kullanabilirsiniz .

Ansible'ın copymodülünü kullanarak uzaktaki ana bilgisayara kopyalayın :

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

Ansible'ın fetchmodülünü kullanarak uzak ana bilgisayardan al :

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

NOT:

  • -i HOST,Sözdizimindeki virgül yazım hatası değil. Bir envanter dosyasına ihtiyaç duymadan ansible kullanmak için yoludur.
  • -bSunucudaki eylemlerin kök olarak yapılmasına neden olur. -bgenişler --becomeve varsayılan --become-user, --become-methodsudo olmak üzere köktür.
  • flat=yessadece dosyayı kopyalar , dosyaya giden tüm uzak yolu kopyalamaz
  • Dosya yollarında joker karakterler kullanmak, bu uyumlu modüller tarafından desteklenmez.
  • Bir dizin kopyalama olduğu desteklediği copyancak, modül değil tarafından fetchmodülü.

Bu soruya özel çağrı

Burada, yerel ana makinenizdeki dizinin dağıtılacak dosyaları içeren dizini sourcedirve uzak hedefin ana makine adı olduğu varsayılarak, özel ve tam olarak belirtilmiş bir örnek verilmiştir hostname:

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

Özlü çağrı ile:

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

PS, "sadece bu muhteşem aracı kur" demenin bir tür sağır cevap olduğunu biliyorum. Ancak , uzak sunucuları yönetmek için süper yararlı olabileceğime karar verdim , bu nedenle yüklemek kesinlikle size dosya dağıtmanın ötesinde başka avantajlar da getirecektir.


Bu cevabı beğendim ancak daha önce oylanmadan önce daha genel bir yorumu yapmak için soruyu yöneltmeni tavsiye ediyorum. gibi bir şeyansible -i "hostname," all -u user --become -m copy -a ...
Mike D

@MikeD: Yukarıdaki değişiklikler nasıl görünüyor?
erik.weathers

1
Bir şey -i 'host,'geçerli bir sözdizimi olur mu? Bir komutu okurken bunun gibi noktalama işaretlerini kaybetmenin kolay olduğunu düşünüyorum. (Okuyucu için demek istediğim, kabuk değilse.)
mwfearnley

1
@mwfearnley: Elbette, kabuk veya -i 'host,'gibi davranacaktır . Genel olarak bu çağrıları göz korkutucu olmalarından korumak için mümkün olduğunca kısa tutmayı tercih ediyorum, ancak açıklık için gerekli olduğunu düşündüğünüz gibi ayrıntılı ve açık yapmaktan çekinmeyin. -i host,-i "host,"
erik.weathers

2
Kutunun dışında düşünmenin yolu!
Ansible'ın

12

Çalıştırdığınızda sudo su, oluşturduğunuz herhangi bir dosya root'a ait olacaktır, ancak ssh veya scp ile doğrudan root olarak giriş yapmak varsayılan olarak mümkün değildir. Ayrıca sudo ile scp kullanmak mümkün değildir, bu yüzden dosyalar kullanılamaz. Dosyalarınız üzerinde sahiplik talep ederek bunu düzeltin:

Kullanıcı adınızın dimitri olduğunu varsayarak, bu komutu kullanabilirsiniz.

sudo chown -R dimitri:dimitri /home/dimitri

O andan itibaren, diğer cevaplarda da belirtildiği gibi, "Ubuntu" yolu, sudo kullanmak ve root oturum açmak değil. Büyük güvenlik avantajları ile faydalı bir paradigmadır.


bu çözümü herhangi bir şekilde kullanıyorum, ancak ne olursa olsun kendi dosya sistemime tam erişim sağlayabilseydim, sudo chow ...her bir dizin için yazmak istemem : S
Dimitris Sapikas 30:12

2
Tüm sistem dosyalarının sahipliğini kullanıcıya kolaylık sağlamak için değiştirmek kesinlikle önerilmez. Sisteminizin güvenliğini ciddi şekilde tehlikeye atmak için karşılaşabileceğiniz tüm kullanıcı alanı hatalarına izin verir. SCP ile değiştirmeniz veya güncellemeniz gereken dosyaların sahipliğini değiştirmek, ancak kökünün sahip olduğu her şeyi (olması gerektiği gibi) bırakmak çok daha iyidir. Yani, söz konusu -Riçinde chownbu dizinin sahipliğini değiştirmek için söyler ve tüm çocukların Dosya ve dizinleri ardışık ... yani sizin gibi her şeyi yapabilir.
trognanders

hmm .... bu iyi çalışıyor gibi görünüyor, teşekkür ederim! Üzgünüm, yükseltemiyorum (sistem yapmama izin vermiyor ...)
Dimitris Sapikas

11

SSH üzerinden kullanmak için en iyi yol rsync( Windows'ta Cygwin / cwRsync ) olabilir mi?

Örneğin, sahibi olan dosyaları yüklemek için www-data:

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

Senin durumunda, kök ayrıcalıklarına ihtiyacın olursa, komut şöyle olacak:

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

Bkz: sudo ile uzak sunucuya scp .


5

PuTTY yerine OpenSSH araçlarını kullanıyorsanız scp, sunucuda dosya aktarımını başlatarak bunu başarabilirsiniz sudo. sshdYerel makinenizde çalışan bir daemon olduğundan emin olun . İle ssh -REğer sunucuyu makinenizi iletişim kurmanın bir yolunu verebilir.

Makinenizde:

ssh -R 11111:localhost:22 REMOTE_USERNAME@SERVERNAME

Sunucuya giriş yapmanıza ek olarak, bu, sunucunun 11111 numaralı bağlantı noktasında yapılan her bağlantıyı makinenizin 22 numaralı bağlantı noktasına yönlendirir: sshddinlediğiniz bağlantı noktası .

Sunucuda, dosya aktarımını şöyle başlatın:

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

1

Bu konudan ilham aldığım senaryoyu kullanabilirsiniz:

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

ama bu biraz çılgınca şeyler gerektirir (btw. otomatik olarak script ile yapılır)

  1. hangi dosyanın gönderildiği sunucu, kaynak bilgisayarla ssh bağlantısı kurarken artık şifre sormayacak
  2. sunucuda sudo istemi eksikliğinin gerekliliği nedeniyle, sudo artık kullanıcı için uzaktaki makinede parola istemeyecek

İşte komut dosyası gider:

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 evet, elbette, bağlantı için üzgünüm, senaryo oldukça uzun ve sebebi buydu :)
test30

1

Ssh, sudo ve örneğin tar komutunu, sunucular arasında kök olarak giriş yapmadan ve dosyalara kullanıcılarınızla erişme izniniz olmadan dosya aktarımı yapmak için birleştirebilirsiniz. Bu biraz titiz, bu yüzden buna yardımcı olacak bir senaryo yazdım. Betiği burada bulabilirsiniz: https://github.com/sigmunau/sudoscp

Veya burada:

#! / Bin / bash
res = 0
= 1 $ 'dan
= $ 2'ye
vardiya
vardiya
dosyaları = "$ @"
eğer -z "$" -o -z "$ den" -o -z "$ dosyalarına"
sonra
    echo "Kullanım: $ 0 (dosya) *"
    echo "örnek: $ 0 sunucu1 sunucu2 / usr / bin / myapp"
    çıkış 1
fi

read -s -p "Şifre Girin:" sudopassword
Eko ""
temp1 = $ (mktemp)
ısı2 = $ (mktemp)
(echo "$ sudopassword"; echo "$ sudopassword" | ssh $ sudo -S tar c-p-c-c / $ dosyaları 2> $ temp1) | ssh $ sudo -S tar x -v-p-c / 2 > $ ısı2
sourceres = $ {PIPESTATUS [0]}
eğer [$? -ne 0 -o $ sourceres -ne 0]
sonra
    yankı "Başarısızlık!" > Ve 2
    echo "$ from output:"> & 2
    cat $ temp1> & 2
    yankı ""> & 2
    echo "$ to output:"> & 2
    cat $ temp2> & 2
    res = 1
fi

rm $ temp1 $ temp2
$ res çık

Ubuntu'ya Sormaya Hoş Geldiniz. Lütfen betiği cevabınıza ekler misiniz? Bunun pek mümkün olmadığını biliyorum ama eğer github deposu daha önce kaldırıldıysa veya url değiştiyse cevap geçersiz olur. Komut dosyasını doğrudan dahil etmek ve github repo'yu kaynak olarak bırakmak daha iyidir.
Michael Lindman

0

İşte Willie Wheeler'ın yanıtını, dosyaları tar yoluyla aktaran, fakat aynı zamanda uzaktaki ana bilgisayarda sudo şifresinin iletilmesini destekleyen bir versiyonudur.

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

Buradaki fazladan sihir biraz sudo seçeneği -S. Sudo man sayfasından:

-S, --stdin Komut istemini standart hataya yazın ve şifreyi terminal cihazı kullanmak yerine standart girişden okuyun. Şifreyi yeni bir satır karakteriyle takip etmelisiniz.

Şimdi aslında tar çıktısının ssh'ye aktarılmasını istiyoruz ve bu da ssh stdin'i tar stdout'a yönlendirerek şifreyi interaktif terminalden sudo'ya aktarmanın herhangi bir yolunu kaldırıyor. (Uzaktaki uçta sudo'nun ASKPASS özelliğini kullanabiliriz, ancak bu başka bir hikaye.) Şifreyi sudo içine alabiliriz, önceden yakalayarak ve bu işlemleri alt kabukta gerçekleştirerek ve çıktısını boruya alarak tar tar çıkışına hazırlayarak alabiliriz. ssh içine subshell. Bu ayrıca, etkileşimli kabuğumuza sarkan şifremizi içeren bir ortam değişkenini bırakmama avantajına da sahiptir.

İstemi yazdırmak için -p seçeneğiyle 'okuma' yapmadığımı fark edeceksiniz. Bunun nedeni, sudo'dan gelen şifre isteminin uygun bir şekilde ssh aracılığıyla etkileşimli kabuğumun stderr'ına geri geçirilmesidir. "Sudo'nun ssh içinde pipomuzun sağına doğru koşması şartıyla nasıl yürüttüğü veriliyor?" Diye merak edebilirsiniz. Birden fazla komut yürüttüğümüzde ve birisinin çıktısını bir diğerine geçirdiğimizde, üst kabuk (bu durumda etkileşimli kabuk), bir önceki komutu uyguladıktan hemen sonra sıradaki her komutu yürütür. Bir borunun arkasındaki her komut çalıştırıldığında, ana kabuk sol tarafın stdoutunu sağ tarafın stdinine tutturur (yönlendirir). Daha sonra çıktı süreçlerden geçerken girdi haline gelir.

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

İnteraktif kabuğumuz PID 7168, alt kabuğumuz PID 7969 ve ssh işlemimiz PID 7970.

Tek dezavantajı, sudo'nun komut istemini geri göndermeye vakti gelmeden önce okumayı kabul etmesidir. Hızlı bir bağlantı ve hızlı bir uzak ana bilgisayarda bunu farketmeyeceksiniz, ancak ya yavaşsa da olabilir. Herhangi bir gecikme bilgi istemine girme yeteneğini etkilemeyecektir; sadece yazmaya başladığınızda görünebilir.

Not Demo için yerel makineme "remote_Host" için bir ana bilgisayar dosyası girişi ekledim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.