เขียนเชลล์สคริปต์เพื่อ ssh ไปยังเครื่องระยะไกลและดำเนินการคำสั่ง


99

ฉันมีสองคำถาม:

  1. มีเครื่องลินุกซ์ระยะไกลหลายเครื่องและฉันต้องเขียนเชลล์สคริปต์ซึ่งจะดำเนินการชุดคำสั่งเดียวกันในแต่ละเครื่อง (รวมถึงการดำเนินการ sudo บางอย่าง) วิธีนี้สามารถทำได้โดยใช้เชลล์สคริปต์?
  2. เมื่อส่งไปยังเครื่องระยะไกลวิธีจัดการเมื่อมีข้อความแจ้งให้ตรวจสอบลายนิ้วมือ RSA

เครื่องระยะไกลคือ VM ที่สร้างขึ้นในขณะทำงานและฉันมี IP ของพวกเขา ดังนั้นฉันจึงไม่สามารถวางไฟล์สคริปต์ล่วงหน้าในเครื่องเหล่านั้นและเรียกใช้งานจากเครื่องของฉันได้


ฉันคิดถึงการปรับใช้โปรแกรมที่เหมือนเอเจนต์ในเครื่อง Linux ระยะไกลซึ่งรักษาการเชื่อมต่อกับเซิร์ฟเวอร์โดยการเชื่อมต่อซ็อกเก็ตเครือข่าย (หรือ SSL) / โดยการสำรวจเป็นระยะไปยังเซิร์ฟเวอร์
Raptor

ฉันต้องการเรียกใช้ชุดคำสั่งเพียงครั้งเดียวดังนั้นจึงไม่จำเป็นต้องรักษาการเชื่อมต่อ
Balanivash

"ไม่มีสคริปต์" หมายความว่า "ไม่มีไฟล์เลย" ฉันคิดว่า? คุณจัดการการรับรองความถูกต้องอย่างไร? คุณสามารถปิดใช้งานการตรวจสอบลายนิ้วมือของโฮสต์ได้ (ดูคำตอบของฉัน) แต่คุณยังคงได้รับข้อความแจ้งรหัสผ่านแบบโต้ตอบหากคุณไม่ได้ตั้งค่าคีย์สาธารณะ / ส่วนตัว
Andreas Fester

1
Andreas: ใช่ ไม่มีไฟล์เลย สามารถจัดการข้อความ passwd โดยใช้ expectเป็น `` คาดหวัง " ? assword: " `
Balanivash

คำตอบ:


142

มีเครื่องลินุกซ์ระยะไกลหลายเครื่องและฉันต้องเขียนเชลล์สคริปต์ซึ่งจะดำเนินการชุดคำสั่งเดียวกันในแต่ละเครื่อง (รวมถึงการดำเนินการ sudo บางอย่าง) วิธีนี้สามารถทำได้โดยใช้เชลล์สคริปต์?

คุณสามารถทำได้ด้วย ssh ตัวอย่างเช่น:

#!/bin/bash
USERNAME=someUser
HOSTS="host1 host2 host3"
SCRIPT="pwd; ls"
for HOSTNAME in ${HOSTS} ; do
    ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"
done

เมื่อส่งไปยังเครื่องระยะไกลวิธีจัดการเมื่อมีข้อความแจ้งให้ตรวจสอบลายนิ้วมือ RSA

คุณสามารถเพิ่มStrictHostKeyChecking=noตัวเลือกใน ssh:

ssh -o StrictHostKeyChecking=no -l username hostname "pwd; ls"

การดำเนินการนี้จะปิดใช้งานการตรวจสอบคีย์โฮสต์และเพิ่มคีย์โฮสต์ลงในรายการโฮสต์ที่รู้จักโดยอัตโนมัติ -o UserKnownHostsFile=/dev/nullหากคุณไม่ต้องการที่จะมีโฮสต์ที่เพิ่มให้กับไฟล์โฮสต์ที่รู้จักกันเพิ่มตัวเลือก

โปรดทราบว่าการดำเนินการนี้จะปิดใช้งานการตรวจสอบความปลอดภัยบางอย่างเช่นการป้องกันการโจมตีจากคนตรงกลาง ดังนั้นจึงไม่ควรนำไปใช้ในสภาพแวดล้อมที่อ่อนไหวด้านความปลอดภัย


ภาษาสคริปต์คืออะไร? แน่นอนคุณสามารถโทรsshจากเชลล์สคริปต์ใดก็ได้
Andreas Fester

แล้วถ้าคุณต้องการทำ CTRL + C และ ssh ต่อไปยังเซิร์ฟเวอร์หลายเครื่องล่ะ? ตัวอย่างเช่นในบางเซิร์ฟเวอร์กำลังขอรหัสผ่านและในบางเซิร์ฟเวอร์ไม่ดังนั้นสคริปต์จะติดอยู่ที่นั่น มีวิธีการทำบางอย่างคล้ายกับ -o สำหรับการทำ CTRL c หรือ CTRL d หรือไม่?
Chanafot

5

มีหลายวิธีในการจัดการกับปัญหานี้

วิธีโปรดของฉันคือการติดตั้งhttp://pamsshagentauth.sourceforge.net/บนระบบระยะไกลและคีย์สาธารณะของคุณเอง (หาวิธีติดตั้งสิ่งเหล่านี้บน VM คุณได้ติดตั้งระบบ Unix ทั้งหมดแล้วไฟล์อีกสองไฟล์คืออะไร)

ด้วยการส่งต่อเอเจนต์ ssh ของคุณตอนนี้คุณสามารถล็อกอินเข้าสู่ทุกระบบได้โดยไม่ต้องใช้รหัสผ่าน

และยิ่งไปกว่านั้นโมดูล pam นั้นจะตรวจสอบสิทธิ์สำหรับ sudo ด้วยคู่คีย์ ssh ของคุณเพื่อให้คุณสามารถรันด้วยสิทธิ์ root (หรือผู้ใช้รายอื่น) ได้ตามต้องการ

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

คุณควรดูแพ็คเกจเช่น Capistrano มองไปรอบ ๆ ไซต์นั้นอย่างแน่นอน มีบทนำสู่การเขียนสคริปต์ระยะไกล

บรรทัดสคริปต์แต่ละบรรทัดอาจมีลักษณะดังนี้:

ssh remote-system-name command arguments ... # so, for exmaple,
ssh target.mycorp.net sudo puppet apply

5

ติดตั้ง sshpass โดยใช้ apt-get install sshpassจากนั้นแก้ไขสคริปต์และใส่ IP ของเครื่อง linux ชื่อผู้ใช้และรหัสผ่านตามลำดับ หลังจากนั้นให้รันสคริปต์นั้น แค่นั้นแหละ ! สคริปต์นี้จะติดตั้ง VLC ในระบบทั้งหมด

#!/bin/bash
SCRIPT="cd Desktop; pwd;  echo -e 'PASSWORD' | sudo -S apt-get install vlc"
HOSTS=("192.168.1.121" "192.168.1.122" "192.168.1.123")
USERNAMES=("username1" "username2" "username3")
PASSWORDS=("password1" "password2" "password3")
for i in ${!HOSTS[*]} ; do
     echo ${HOSTS[i]}
     SCR=${SCRIPT/PASSWORD/${PASSWORDS[i]}}
     sshpass -p ${PASSWORDS[i]} ssh -l ${USERNAMES[i]} ${HOSTS[i]} "${SCR}"
done

1
ใช้ $ SSHPASS เพื่อส่งออกรหัสผ่านเพื่อหลีกเลี่ยงไม่ให้แสดงในสคริปต์ Ref: tecmint.com/…
Hexy

3

งานนี้สำหรับฉัน

ไวยากรณ์: ssh -i pemfile.pem user_name @ ip_address 'command_1; คำสั่ง 2; คำสั่ง 3 '

#! /bin/bash

echo "########### connecting to server and run commands in sequence ###########"
ssh -i ~/.ssh/ec2_instance.pem ubuntu@ip_address 'touch a.txt; touch b.txt; sudo systemctl status tomcat.service'

2

ถ้าคุณมีความสามารถในการเขียนรหัส Perl แล้วคุณควรพิจารณาการใช้สุทธิ :: OpenSSH :: ขนาน

คุณจะสามารถอธิบายการดำเนินการที่ต้องดำเนินการในทุกโฮสต์ในลักษณะที่เปิดเผยและโมดูลจะดูแลรายละเอียดที่น่ากลัวทั้งหมด sudoนอกจากนี้ยังรองรับการรันคำสั่งผ่าน


1

สำหรับงานประเภทนี้ฉันใช้Ansibleซ้ำ ๆซึ่งอนุญาตให้ทำซ้ำ bash scripts ที่สอดคล้องกันในหลายคอนเทนเนอร์หรือ VM Ansible ( Red Hat ที่แม่นยำยิ่งขึ้น) ตอนนี้มีเว็บอินเตอร์เฟสเพิ่มเติมAWXซึ่งเป็นรุ่นโอเพ่นซอร์สของ Commercial Tower

ตอบได้: https://www.ansible.com/
AWX: https://github.com/ansible/awx
Ansible Tower: ผลิตภัณฑ์เชิงพาณิชย์คุณอาจจะลองใช้ AWX แบบโอเพนซอร์สฟรีแทนที่จะเป็นเส้นทางฟรี 15 วัน ของ Tower


1

มีหลายวิธีในการดำเนินการคำสั่งหรือสคริปต์ในเครื่อง Linux ระยะไกลหลายเครื่อง วิธีหนึ่งที่ง่ายและง่ายที่สุดคือผ่านpssh (โปรแกรม ssh คู่ขนาน)

pssh : เป็นโปรแกรมสำหรับดำเนินการ ssh พร้อมกันบนโฮสต์จำนวนมาก มีคุณสมบัติเช่นการส่งอินพุตไปยังกระบวนการทั้งหมดการส่งรหัสผ่านไปยัง ssh การบันทึกเอาต์พุตไปยังไฟล์และการหมดเวลา

ตัวอย่างและการใช้งาน:

เชื่อมต่อกับ host1 และ host2 แล้วพิมพ์ "hello, world" จากแต่ละรายการ:

 pssh -i -H "host1 host2" echo "hello, world"

เรียกใช้คำสั่งผ่านสคริปต์บนเซิร์ฟเวอร์หลายเครื่อง:

pssh -h hosts.txt -P -I<./commands.sh

การใช้งานและเรียกใช้คำสั่งโดยไม่ต้องตรวจสอบหรือบันทึกคีย์โฮสต์:

pssh -h hostname_ip.txt -x '-q -o StrictHostKeyChecking=no -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes' -i  'uptime; hostname -f'

หากไฟล์ hosts.txt มีรายการจำนวนมากให้พูดว่า 100 ดังนั้นตัวเลือกการขนานอาจถูกตั้งค่าเป็น 100 เพื่อให้แน่ใจว่าคำสั่งทำงานพร้อมกัน:

pssh -i -h hosts.txt -p 100 -t 0 sleep 10000

ตัวเลือก :
-I:อ่านอินพุตและส่งไปยังแต่ละกระบวนการ ssh
-P:บอกให้ pssh แสดงผลลัพธ์เมื่อมาถึง
-h:อ่านไฟล์ของโฮสต์
-H: [user @] โฮสต์ [: port] สำหรับโฮสต์เดียว
-i:แสดงเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐานเมื่อแต่ละโฮสต์ดำเนินการเสร็จสิ้น
-x args:ส่งผ่านอาร์กิวเมนต์บรรทัดคำสั่ง SSH เพิ่มเติม
อ็อพชัน -o:สามารถใช้เพื่อระบุอ็อพชันในรูปแบบที่ใช้ในไฟล์คอนฟิกูเรชัน (/ etc / ssh / ssh_config ) (~ / .ssh / config)
-p parallelism:ใช้ตัวเลขที่กำหนดเป็นจำนวนสูงสุดของการเชื่อมต่อพร้อมกัน
-q โหมดเงียบ: ทำให้ข้อความเตือนและการวินิจฉัยส่วนใหญ่ถูกระงับ
-t:ทำให้การเชื่อมต่อหมดเวลาหลังจากจำนวนวินาทีที่กำหนด 0 หมายความว่า pssh จะไม่หมดเวลาการเชื่อมต่อใด ๆ

เมื่อส่งไปยังเครื่องระยะไกลวิธีจัดการเมื่อมีข้อความแจ้งให้ตรวจสอบลายนิ้วมือ RSA

ปิดใช้งาน StrictHostKeyChecking เพื่อจัดการพรอมต์การพิสูจน์ตัวตน RSA
-o StrictHostKeyChecking = ไม่

ที่มา : man pssh


0

สิ่งนี้ได้ผลสำหรับฉัน ฉันทำหน้าที่ ใส่สิ่งนี้ในเชลล์สคริปต์ของคุณ:

sshcmd(){
    ssh $1@$2 $3
}

sshcmd USER HOST COMMAND

หากคุณมีหลายเครื่องที่คุณต้องการทำคำสั่งเดียวกันคุณจะต้องทำซ้ำบรรทัดนั้นด้วยเซมิโคลอน ตัวอย่างเช่นหากคุณมีสองเครื่องคุณจะทำสิ่งนี้:

sshcmd USER HOST COMMAND ; sshcmd USER HOST COMMAND

แทนที่ USER ด้วยผู้ใช้คอมพิวเตอร์ แทนที่ HOST ด้วยชื่อของคอมพิวเตอร์ แทนที่ COMMAND ด้วยคำสั่งที่คุณต้องการทำบนคอมพิวเตอร์

หวังว่านี่จะช่วยได้!


-1

คุณสามารถทำตามแนวทางนี้:

  • เชื่อมต่อไปยังเครื่องระยะไกลโดยใช้คาดหวังสคริปต์ หากเครื่องของคุณไม่รองรับคุณสามารถดาวน์โหลดได้ การเขียนสคริปต์ Expect นั้นง่ายมาก (Google เพื่อขอความช่วยเหลือในเรื่องนี้)
  • ใส่การดำเนินการทั้งหมดที่ต้องดำเนินการบนเซิร์ฟเวอร์ระยะไกลในเชลล์สคริปต์
  • เรียกใช้สคริปต์เชลล์ระยะไกลจากสคริปต์ที่คาดหวังเมื่อล็อกอินสำเร็จ

ดังที่ฉันได้กล่าวไว้ในคำถามเครื่องระยะไกลถูกสร้างขึ้นในขณะทำงานและฉันไม่สามารถมีสคริปต์ใด ๆ ในเครื่องได้ล่วงหน้า
Balanivash

ในกรณีนั้นให้ดำเนินการทั้งหมดในสคริปต์ Expect คาดหวังว่าสคริปต์สามารถรันคำสั่งได้เช่นกันบนโฮสต์ระยะไกล
rai.skumar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.