Bir SSH komutuna parola sağlamak için Bash komut dosyasında Expect'i kullanın


131

Expect'i bir Bash komut dosyasında SSH şifresini sağlamak için kullanmaya çalışıyorum. Parolayı sağlamak işe yarıyor, ancak gerektiği gibi SSH oturumuna girmiyorum. Bash'e geri dönüyor.

Senaryom:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com'
expect "password"
send "$PWD\n"
EOD
echo "you're out"

Komut dosyamın çıktısı:

spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
usr@$myhost.example.com's password: you're out

SSH oturumumun olmasını ve yalnızca ondan çıktığımda Bash betiğime geri dönmek istiyorum.

Bash'i Expect'ten önce kullanmamın nedeni, bir menü kullanmak zorunda olmam. Hangi üniteye / cihaza bağlanacağımı seçebilirim.

SSH anahtarlarını kullanmam gerektiğini söyleyenler lütfen çekimser kalsınlar.


49
İlk satırı bakın: isteyenler cevap için ben SSH tuşlarını kullanın çekimser razı etmeleri
Max

54
İlk satırınızı biraz daha dostça olacak şekilde düzenlerdim. "Kısıtlamalar nedeniyle, SSH anahtarlarını kullanamıyorum, beklendiği gibi çalıştırmanın bir yolunu bulmalıyım" gibi bir şey düşünebilirsiniz. İnsanların doğal olarak neden anahtarları kullanmadığınızı merak etmelerini ve sadece yardımcı olmaya çalıştıklarını beklemelisiniz :) @Ignacio bunları kullanmanızı önermedi , sadece bir kısıtlama olarak onaylıyordu, bir gözetim değil.
Tim Post

Bu durumda kermit kullanmaya çalışırdım. Bu sahiptir çok sağlam kodlama dili columbia.edu/kermit/skermit.html#scripts
f3xy

Yanıtlar:


86

Bash ve Expect'i karıştırmak, istenen etkiyi elde etmenin iyi bir yolu değildir. Yalnızca Expect'i kullanmayı denerim:

#!/usr/bin/expect
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com

# Use the correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "my_password\r"
interact -o -nobuffer -re $prompt return
send "my_command1\r"
interact -o -nobuffer -re $prompt return
send "my_command2\r"
interact

Bash için örnek çözüm şunlar olabilir:

#!/bin/bash
/usr/bin/expect -c 'expect "\n" { eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com; interact }'

Bu bekleyecek Enterve sonra (bir anlığına) etkileşimli oturuma dönecektir.


1
harika çalışıyor, teşekkürler. SSH ile oturum açtıktan sonra komut yazmak istersem ne yapmam gerekir?
Max

Bu komut dosyası, oturum açmış kullanıcıyla etkin olmayan kabuk döndürmelidir. Ben soruyu anlamıyorum. Bash'de kesinlikle aynı betiği kullanmak istiyorsanız, düzenlenen girişe bakın.
Piotr Król

İstendiğinde şifreyi gönderdiğim gibi, oturum açtıktan sonra sistem komutları göndermek istiyorum.
Fazla

Samlple kodu yukarıdaki gönderiye eklendi. Elbette bu, my_commandX döndürülen istemi değiştirene kadar çalışacaktır, eğer bu olursa komut değişkeni değiştirilmelidir.
Piotr Król

@pietrushnic, neden "$ istem beklemek" yerine "etkileşimli -o -nobuffer -re $ istem dönüşü" kullandığınızı biraz açıklayabilir misiniz? ikincisi daha sık kullanılan görünüyor ..
Richard

53

En kolay yol sshpass kullanmaktır . Bu, Ubuntu / Debian depolarında mevcuttur ve Bash ile beklentileri entegre etmek zorunda kalmazsınız.

Bir örnek:

sshpass -p<password> ssh <arguments>
sshpass -ptest1324 ssh user@192.168.1.200 ls -l /tmp

Yukarıdaki komut, bir Bash betiği ile kolayca entegre edilebilir.

Not: Güvenlik etkilerini tam olarak anlamak için lütfen Güvenlik Hususları bölümünü okuyun man sshpass.


İyi bir çözüm olup olmadığını bilmiyorum ama kesinlikle çok basitleştiriyor. Teşekkürler
erikbwork

9
Güvenlik açısından çok tehlikeli - komut satırı argümanları sistemdeki herhangi bir işlem tarafından okunabilir. Bunların üzerine yazmak mümkündür ve umarım sshpassbunu yapar, ancak o zaman bile, parola herhangi / her işlem için mevcut olduğunda bunu yapmadan önce hala başlamışken bir süre vardır.
Charles Duffy

1
@CharlesDuffy Tabii ki haklısın. sshpassgüvenliğin en önemli konu olmadığı yerel bir ağ ortamında yürütülen basit test komut dosyalarına sahip olduğunuz bir senaryoda kullanılır. Aslında, man sshpassGüvenlik Hususları ile ilgili bütün bir bölümün açıklandığı bir bölüm var. Bunu cevaba eklendi, Teşekkürler.
dotnix

@ erikb85 Genellikle, bir paket sizin için tüm kirli şeyleri yapar, ancak her durumda, bu komut dosyaları yalnızca bu kullanım için oluşturulmuştur, bu durumda kendi dosyalarınızı eklemekten DAHA İYİ olur. Bu yorum tekerleği yeniden icat etmemekle ilgili. Zor işlerle ancak henüz kimse ilgilenmediyse ilgilenin. sshpass bu iyi bir işlevdir.
m3nda

2
Tamlık adına, "man sshpass" ın olası kullanıcıya uygun güvenlik uyarıları sunduğunu, "-p" nin en az güvenli yol olduğuna işaret ettiğini ve şifreyi ortam değişkeni üzerinden almak için "-e" seçeneğini sunduğunu belirtiyorum. , bu en azından onu komut satırının dışında tutar.
Ron Burk

22

EOD'nizden hemen önce 'etkileşimli' Bekle komutunu ekleyin:

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
expect "password"
send "$PWD\n"
interact
EOD
echo "you're out"

Bu, siz oturumu kapatana kadar uzak makineyle etkileşim kurmanıza izin vermelidir. Sonra Bash'e geri döneceksin.


Hemen girer ve hemen çıkar. "çıktın" yazdırılır.
Emmanuel

8
"Etkileşim" ve "EOD" yi "eof beklemek" ile değiştirdim ve benim için çalıştı. Bu bir Mac'te.
Emmanuel

2
Bu sayfadaki cevapların hiçbiri benim için işe yaramadı ama @ Emmanuel'in kullanma önerisi expect eofsorunu çözdü.
moertel

Kaldır 'dan usr@$myhost.example.com've çalışması gerekir. Ve belki de değiştirmeniz gerekiyor \nile \r, ymmv
Tino

20

Aylarca sorunun cevabını aradıktan sonra, sonunda gerçekten en iyi çözümü buldum: basit bir senaryo yazmak.

#!/usr/bin/expect

set timeout 20

set cmd [lrange $argv 1 end]
set password [lindex $argv 0]

eval spawn $cmd
expect "Password:"
send "$password\r";
interact

İçine koyun /usr/bin/exp, sonra kullanabilirsiniz:

  • exp <password> ssh <anything>
  • exp <password> scp <anysrc> <anydst>

Bitti!


expect "assword:"Ne demek mi expect "password:"?
kullanıcı

1
@user "assword"hem Passwordve ile eşleşir password.
Ferdinand.kraft

8

Ayrıca kullandığınızdan emin olun

send -- "$PWD\r"

bunun yerine, aksi takdirde tire (-) ile başlayan parolalar başarısız olacaktır.

Yukarıdakiler, tire ile başlayan bir dizeyi gönderme komutuna bir seçenek olarak yorumlamaz.


8

Basit bir Expect komut dosyası:

Dosya Remotelogin.exp

    #!/usr/bin/expect
    set user [lindex $argv 1]
    set ip [lindex $argv 0]
    set password [lindex $argv 2]
    spawn ssh $user@$ip
    expect "password"
    send "$password\r"
    interact

Misal:

./Remotelogin.exp <ip> <user name> <password>

7

Yardımcı aracı kullanın fd0ssh(pmt değil, hxtools'dan). sshProgramdan belirli bir uyarı beklemek zorunda kalmadan çalışır .


Bu harika! Çalıştırması biraz zor (en azından ubuntu sunucusunda) ama sorunsuz çalışıyor! Yaptığımız yapılandırma: echo "yoursshpass" | fd0ssh ssh -c -L$port:$ip:$remote_port user@yourserver.com & TEŞEKKÜRLER!
JP Illanes

1
Şifreyi komut satırından geçirmekten çok daha güvenli sshpass.
Charles Duffy

5

Bash betiğinden küçük bir Expect betiği kullanmanın yararlı bulduğum başka bir yolu da aşağıdaki gibidir.

...
Bash script start
Bash commands
...
expect - <<EOF
spawn your-command-here
expect "some-pattern"
send "some-command"
...
...
EOF
...
More Bash commands
...

Bu işe yarıyor çünkü ...If the string "-" is supplied as a filename, standard input is read instead...


Herhangi bir argüman olmadan çağırırsanız, varsayılan -olarak expectokunduğu gibi , buraya ihtiyacınız yoktur stdin. Bununla birlikte, komut istemi olmadan etkileşimli olarak çalıştırmak istiyorsanız ( expectvs. expect -) veya expect -f "$@"bir seçenek gibi görünse bile (ile başlar -) ilk argümanın bir dosya olacağı gibi bir şey yapmanız durumunda kullanışlıdır . Bu durumda, eğer $1(verilen dosya) -bu ise okur stdin.
Tino

1

sshpassMakefile içinde bir Sublime Text yapı hedefi içinde kullanmaya çalışırsanız bozulur . Bunun yerine şunu sshpasskullanabilirsiniz passh: https://github.com/clarkwang/passh

Seninle sshpassyapardın:

sshpass -p pa$$word ssh user@host

Seninle passhyapardın:

passh -p pa$$word ssh user@host

Not: Kullanmayı unutmayınız -o StrictHostKeyChecking=no. Aksi takdirde, bağlantı ilk kez kullandığınızda takılır. Örneğin:

passh -p pa$$word ssh -o StrictHostKeyChecking=no user@host

Referanslar:

  1. SSH bağlantısında Expect komut dosyası kullanılarak parola için gönderme komutu çalışmıyor
  2. Ssh'da sıkı ana bilgisayar anahtarı denetimini nasıl devre dışı bırakabilirim?
  3. SSH ana bilgisayar anahtarı denetimi nasıl devre dışı bırakılır
  4. bilinen_hosts kontrolü olmadan scp
  5. pam_mount ve parola kimlik doğrulamalı sshfs
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.