ด้วย ssh คุณจะรันคำสั่งบนเครื่องรีโมตโดยไม่ออกได้อย่างไร?


29

โดยปกติถ้าคุณส่งคำสั่งไปยัง ssh อย่างนั้น

ssh me@example.com 'some-command.sh'

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

ssh me@example.com 'screen -r 12345'

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

เป็นอีกตัวอย่างหนึ่งฉันใช้เครื่องจักรจำนวนมากในการทำงานซึ่งมักทำให้ฉันต้องใช้บัญชีที่ใช้ร่วมกันเพื่อมีสิทธิ์ทำบางสิ่ง (ใช่ฉันรู้ว่า: ความคิดที่ไม่ดี แต่ไม่โทษฉัน วิธี) และพวกเขามักจะมี ksh เป็นเปลือกเริ่มต้น ฉันต้องการลงชื่อเข้าใช้สลับไปยัง bash (หรือ zsh) และหา. bash_profile (หรือ. zshrc) บัญชีของฉันเอง นี่จะเป็นเรื่องง่ายถ้าฉันสามารถสร้างเซสชัน ssh แบบโต้ตอบและส่งคำสั่งไปยังเครื่องระยะไกลเพื่อเรียกใช้เมื่อเข้าสู่ระบบ

ฉันมีโซลูชัน kludgey (และยังไม่ทดลอง) ในใจว่าฉันจะโพสต์ แต่ฉันหวังว่าจะมีคนรู้วิธีที่ดีกว่า

UPDATE: สำหรับผู้ที่ไม่ได้ตระหนักถึงสิ่งนี้ฉันไม่ได้วางแผนที่จะทำสิ่งนี้ด้วยมือดังนั้นบอกให้ฉันเปิดเซสชันแบบโต้ตอบและจากนั้นทำด้วยมือไม่ได้แก้ปัญหาอะไรเลย

ปรับปรุงครั้งที่ 2: เพื่อพยายามชี้แจงอีกครั้ง: ฉันพยายามเรียกใช้คำสั่ง (โดยพลการ) บนเซิร์ฟเวอร์ (ระบุโดยโปรแกรมบนไคลเอนต์) แต่เปิดเซสชันแบบโต้ตอบที่ได้รับผลกระทบจากสิ่งใดก็ตามที่ทำโดยคำสั่งแบบโปรแกรมเหล่านั้น


echo "command" | ssh user@remote_host
laggingreflex

2
คุณพลาดส่วน "โดยไม่ต้องออก" หรือไม่? ฉันค่อนข้างแน่ใจว่าจะออกหลังจากคำสั่งเสร็จสิ้น
iconoclast

คำตอบ:


26

คุณสามารถลองใช้คำสั่งต่อไปนี้เพื่อเริ่มต้นการทุบตีและแหล่งโปรไฟล์ของคุณเองเมื่อคุณ ssh:

ssh  -t hostname "bash --rcfile ~user/.bashrc"

4
+1 -tสวิทช์แก้ไขปัญหาถามด้วยscreenเช่นกัน
แพทช์

3
สามารถใช้กับคำสั่งโดยพลการโดยไม่ปิดการเชื่อมต่อได้หรือไม่? หากฉันลองssh -t www.dev "echo 'hi there'"การเชื่อมต่อจะปิดทันทีหลังจากดำเนินการคำสั่ง
iconoclast

11

จากคำตอบของ dogbane โซลูชันที่สมบูรณ์ดูเหมือนว่า:

ssh -t user@server 'cd /a/great/place; bash'

ที่นี่ฉันใช้-tเพื่อบังคับการจัดสรรของเทอร์มินัลหลอกซึ่งจำเป็นสำหรับเชลล์แบบโต้ตอบ จากนั้นฉันรันคำสั่งสองคำสั่งบนเซิร์ฟเวอร์: สิ่งแรกที่ฉันต้องการทำก่อนที่จะเปิดเชลล์แบบโต้ตอบ (ในกรณีของฉันเปลี่ยนไดเรกทอรีไปยังโฟลเดอร์เฉพาะ) จากนั้นเชลล์แบบโต้ตอบเอง bash เห็นว่ามันมีขั้วหลอกและตอบสนองแบบโต้ตอบ

อัญประกาศเดี่ยวให้แน่ใจว่าสิ่งทั้งหมดถูกส่งผ่านไปยังเซิร์ฟเวอร์ระยะไกลเป็นคำสั่งที่จะทำงานโดยเปลือกเริ่มต้นของคุณ

ขอขอบคุณอีกครั้งที่จะ dogbane -tสำหรับการให้เบาะแสที่จำเป็นด้วย ฉันเคยแก้ปัญหานี้ด้วยexpectซึ่งแน่นอนว่าการฆ่าหนูด้วยปืนใหญ่ (:


2

ลองวิธีนี้

echo "command" | ssh user@remote_host

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

ssh user@remote_host 'command'

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

อย่างน้อยก็เป็นการดีที่จะจำลองการโต้ตอบสำหรับคำสั่งเพื่อดำเนินการโดยไม่ต้องใช้-tหรือไฟล์ทุบตีของคุณเอง +1
laggingreflex

0

ใช้ ssh -X เพื่อใช้ termIO cmds

นอกจากนี้ - คุณสามารถโยง cmds ของคุณเช่น "ssh 'source ~ / .bashrc && cd && do'"


แต่หลังจากเสร็จสิ้นทั้งเครือฉันไม่เหลือเซสชันการโต้ตอบใช่ไหม มันยังปิดอยู่ใช่ไหม
iconoclast

และคุณสนใจที่จะอธิบายรายละเอียดเกี่ยวกับโซลูชัน termIO หรือไม่
iconoclast

0

ทำไมไม่ติดตั้งdetachบนระบบรีโมตและใช้:

ssh -t user@example.com "/home/user/bin/detach ls"

การทำงานนี้ 'ls' และจะทิ้งฉันไว้กับเซสชันแบบโต้ตอบหรือไม่ จะทำอย่างไรถ้าแทนที่จะเป็น 'ls' ฉันจะเรียกใช้ 'source .somefile' เพื่อรับนามแฝงและฟังก์ชันบางอย่าง พวกเขาจะพร้อมใช้งานในเซสชันการโต้ตอบของฉันหรือจะถูกเรียกใช้ในเซสชันอื่นหรือไม่
iconoclast

ไม่มีเนื่องจากdetach, lsไม่ให้เซสชั่นเปิดและจะตัดการเชื่อมต่อโดยไม่ต้องพิมพ์การส่งออกของlsแต่จะยังคงทำงาน
Dan D.

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

0

คำตอบของ laggingreflex ใกล้แล้ว ... ฉันจะเปลี่ยนดังนี้:

echo "command\n$(cat -)" | ssh user@remote_host

น่าเสียดายที่คุณไม่ชอบวิธีการทำงาน 'ทำให้ "cat" บัฟเฟอร์บรรทัดที่เขียนไปยัง stdout ... หากเราสร้างสคริปต์ชื่อ "echo-cat" ที่มีลักษณะดังนี้:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

เราจะได้ผลลัพธ์เดียวกันโดยไม่บัฟเฟอร์:

echo-cat "command" | ssh user@remote_host

นั่นอาจทำให้คุณใกล้ชิดกับวัตถุประสงค์ของคุณมากขึ้น ...


0

นี่คือ kludgey และยังไม่ทดลอง แต่ฉันคิดว่ามันควรจะใช้ได้

สร้างสคริปต์ชื่อ (เช่น) รีโมตสตาร์ทเตอร์ที่รับอาร์กิวเมนต์ที่ยกมาหลังจากอาร์กิวเมนต์ user @ host:

remote-starter user@example.com 'some-command.sh arg1 arg2'

สคริปต์นี้ควรบันทึกคำสั่งที่ยกมา (ไม่มีเครื่องหมายคำพูด) ในไฟล์ชื่อ (เช่น) .onetimeบนเครื่องระยะไกลจากนั้นเรียกใช้คำสั่ง ssh ปกติคราวนี้จะไม่ส่งคำสั่งใด ๆ เพื่อเรียกใช้บนเครื่องระยะไกล (หากเรียกใช้ ssh user@example.com จากภายในสคริปต์อาจทำงานเพื่อเรียกใช้ exec ssh user@example.com)

เพื่อให้การทำงานเครื่องระยะไกลต้องมา.onetimeจาก. bash_profile หรือ. zshrc หรืออะไรก็ตาม หลังจากรัน.onetimeแล้วควรลบ.onetimeดังนั้นไฟล์จะไม่ทำงานในครั้งต่อไปที่คุณเข้าสู่ระบบปกติ

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