วิธีรันคำสั่ง sudo ด้วยคำสั่ง Expect & send ใน bash script


10

ใครช่วยให้ฉันรู้วิธีการดำเนินการsudoคำสั่งด้วยexpect? ฉันลองสิ่งต่อไปนี้ แต่มันไม่ทำงาน ใครช่วยแนะนำฉันหน่อยได้ไหม

set login "sasuke"
set addr "hostname"
set pw "mypasswd"
spawn ssh $login@$addr
expect "$login@$addr\'s password:"
send "$pw\r"
expect "#"
send "output=$(sudo virsh list --all | awk "/running/{print \$2}" | tail -2); sudo virsh dominfo $output"
expect "password:"
send "$pw\r"
expect "#"

เมื่อฉันลองสคริปต์ด้านล่างมันทำงานโดยไม่มีข้อผิดพลาด แต่ฉันไม่ได้รับผลลัพธ์ นี่คือสคริปต์และเอาต์พุตเมื่อเรียกใช้งาน ฉันทำผิดที่นี่ที่ไหน

set login "sasuke"
set addr "hostname"
set pw "mypasswd"
spawn ssh $login@$addr
expect "$login@$addr's password:"
send "$pw\r"
expect "#"
send {output=$(sudo virsh list --all | awk '/running/{print $2}' | tail -2)}
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}
send {sudo virsh dominfo "$output"}    ;# don't know if you need quotes there
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}

การกระทำ

sasuke@njob:~$ ./hypr.sh 
spawn ssh sasuke@hostname 
sasuke@hostname's password: 
sasuke@hostname:~$ output=$(sudo virsh list --all | awk '/running/{print $2}' | tail -10)sudo virsh dominfo '$output' sasuke@njob:~$

คำตอบ:


10
set login "sasuke"
set addr "hostname"
set pw "mypasswd"
spawn ssh $login@$addr
expect "$login@$addr's password:"
send "$pw\r"
expect "#"
send {output=$(sudo virsh list --all | awk '/running/{print $2}' | tail -2)}
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}
send {sudo virsh dominfo "$output"}    ;# don't know if you need quotes there
expect {
    password: {send "$pw\r"; exp_continue}
    "#"
}

ใน Tcl (และ, โดยการขยาย, คาดหวัง), วงเล็บปีกกาทำหน้าที่เหมือนเครื่องหมายคำพูดเดี่ยวของเชลล์: ยับยั้งการขยายตัวของตัวแปร

รูปแบบที่คาดหวังหลายรูปแบบมีประโยชน์สำหรับกรณีที่คุณอาจไม่เห็นรูปแบบ exp_continueคำสั่งเป็นหลัก "ลูป" ภายในคาดหวังเพื่อให้คุณสามารถส่งรหัสผ่านและยังคงคาดหวังว่าพรอมต์ เนื่องจากไม่มีการดำเนินการที่เกี่ยวข้องกับรูปแบบพรอมต์การควบคุมผ่านจากคำสั่ง expect ไปยังอีกรูปแบบหนึ่ง

ฉันขอแนะนำให้คุณบันทึกเป็นสคริปต์แยกต่างหาก บรรทัดแรกควรเป็น

#!/usr/bin/expect -f

หากคุณต้องการฝังในสคริปต์เชลล์:

#!/bin/sh
expect <<'END'
   # code as above
END

สังเกตเครื่องหมายคำพูดรอบ "END" ตัวแรก - ซึ่งมีผลของการอ้างถึงเอกสารทั้งหมดที่นี่เพียงครั้งเดียวดังนั้นคุณไม่ต้องกังวลเกี่ยวกับเชลล์ที่จะตีความตัวแปรคาดหวัง


สวัสดีเกล็นสคริปต์กำลังดำเนินการโดยไม่มีข้อผิดพลาด แต่ฉันไม่สามารถเห็นผลลัพธ์ของ Scirpt ฉันทำอะไรผิดในสคริปต์ ถ้าใช่โปรดแจ้งให้ฉันทราบฉันบันทึกผลลัพธ์ในไฟล์แยกต่างหาก นี่คือสคริปต์ที่ฉันกำลังเรียกใช้ sasuke @ njob: ~ $ ./hypr.sh วางไข่ ssh sasuke @ ชื่อโฮสต์ sasuke @ รหัสผ่านของชื่อโฮสต์: sasuke @ hostname: ~ $ output = $ (รายการ sudo virsh - ทั้งหมด | awk '/ running / {print $ 2} '| tail -10) sudo virsh dominfo' $ output 'sasuke @ njob: ~ $
sasuke

คุณไม่สามารถโพสต์รหัสในความคิดเห็นได้โปรดเพิ่มในคำถามของคุณ
glenn jackman

โอ้ฉันขอโทษที่ ขอบคุณฉันทำมัน กรุณาช่วยฉันออกไป.
สึเกะ

ไม่ทราบ เพิ่มexp_internal 1ที่ด้านบนสุดของสคริปต์และอ่านเอาต์พุต verbose
เกล็นแจ็คแมน

3

ฉันต้องการแบ่งปันเรื่องน่าสนใจของฉัน ฉันลองสิ่งนี้ในระบบของฉัน มันใช้งานได้ดี

#!/usr/bin/expect
set username "myname"
set password "mypasswd"
set hosts "hostname"
foreach line [split $ip \n] {
spawn ssh -o StrictHostKeyChecking=no $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "sudo virsh list|awk '{print \$2}'|grep 'inmobi' >vm.list; for host in `cat vm.list`; do sudo virsh dominfo \$host >> vm.info; done\n"
expect "$"
send -- "$password\n"
expect "$"
send -- "exit\n"

1

พยายามที่จะจบด้วยคำสั่ง "โต้ตอบ" มันควรจะทำงาน

spawn ssh -l $username $ip -p $sshport
sleep 5
expect "password:"
send "$pass\r"
interact

0

ฉันคิดว่าคุณอาจต้องแบ็กสแลชเครื่องหมายคำพูดภายในเครื่องหมายคำพูด มิฉะนั้นexpectคิดว่าคำสั่งจะจบลงหลังจาก "awk":

send "output=$(sudo virsh list --all | awk \"/running/{print \$2}\" | tail -2); sudo virsh dominfo $output"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.