`ssh <host>` เป็นเชลล์การเข้าสู่ระบบ แต่ `ssh <host> <command>` ไม่ใช่?


12

ฉันสังเกตว่าเมื่อฉันเรียกใช้คำสั่งโดยตรงบนโฮสต์ SSH โดยใช้ssh <host> <command>ไวยากรณ์ฉันเห็นผลลัพธ์ของ.bashrcแต่ไม่ใช่ผลลัพธ์ของ.bash_profile(หรือ.profile)

ตัวอย่างเช่นถ้าฉันวางคำสั่งต่อไปนี้ที่ด้านบนของไฟล์ทั้งสอง

echo ${BASH_SOURCE[0]}

และแหล่งที่มาด้วยตนเอง.bash_profile(ที่มา.bashrcในการเปิด) ฉันจะเห็น

$ . .bash_profile
.bash_profile
.bashrc

นี่เป็นผลลัพธ์เดียวกันกับที่ฉันเห็นว่าฉันลงชื่อเข้าใช้คอมพิวเตอร์เครื่องนี้จากระยะไกลผ่าน SSH โดยใช้ssh <host>รูปแบบของคำสั่ง (และถ้าฉันเก็บไว้ที่.bash_profileอื่นชั่วคราวบรรทัดเหล่านี้จะไม่ถูกสะท้อนเลย)

อย่างไรก็ตามถ้าฉันรันคำสั่งบนเครื่องรีโมตโดยตรงด้วยssh <host> <command>รูปแบบของsshเอาต์พุตจะมีลักษณะดังนี้:

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

ความเข้าใจของฉันอยู่ที่ความแตกต่างระหว่าง.bash_profileและ.bashrcเป็นว่าอดีตเป็นเปลือกหอยเข้าสู่ระบบในขณะที่หลังสำหรับการโต้ตอบและเปลือกหอยที่ไม่เข้าสู่ระบบ

ฉันได้ข้อสรุปดังต่อไปนี้:

  1. ssh <host>แหล่งที่มาเท่านั้น.bash_profileในขณะที่
  2. ssh <host> <command>แหล่งข้อมูลเท่านั้น.bashrcซึ่งหมายถึง
  3. อดีตเป็นเปลือกเข้าสู่ระบบและหลังไม่ได้

ข้อสรุปเหล่านี้ถูกต้องหรือไม่ เหตุใดจึงssh <host> <command>ถือว่าเป็นเชลล์แบบโต้ตอบและไม่ใช่การเข้าสู่ระบบ SSH ยังไม่ได้เข้าสู่เครื่องระยะไกลเพื่อดำเนินการคำสั่งหรือไม่


การส่งออกของ.bashrc? ไฟล์นั้นไม่ควรสร้างเอาต์พุตใด ๆ เอาต์พุตใด ๆ จาก.bashrcสามารถทำลายเครื่องมือทั้งหมดโดยใช้ ssh เป็นการขนส่งของพวกเขา
kasperd

ยุติธรรมพอสมควร ในกรณีนี้มีสองบรรทัดที่.bashrcกำลังโยนข้อผิดพลาดในขณะที่บรรทัดที่คล้ายกัน.bash_profileไม่ใช่ ฉันใช้โอกาสตรวจสอบความคลาดเคลื่อนก่อนแก้ไขบรรทัดที่ละเมิด
Ryan Lue

คำตอบ:


12

OpenSSH (ส่วนใหญ่สิ่งที่คุณกำลังเรียกใช้) ตัดสินใจว่าจะสร้างเชลล์ล็อกอินหรือไม่และจะทำเช่นนั้นหากคุณไม่ได้ใช้คำสั่งเฉพาะ จากman ssh:

 If command is specified, it is executed on the remote host instead of a
 login shell.

ดังนั้นจึงเป็นตัวเลือกการนำไปใช้งานสำหรับเซิร์ฟเวอร์ ssh ไม่ว่าจะต้องการสร้างเชลล์ล็อกอินหรือไม่และถ้าคุณให้คำสั่งเพื่อรันมันจะไม่ทำงาน

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

พวกเขาสร้างเชลล์ที่ไม่ต้องมีการโต้ตอบและไม่ได้ลงชื่อเข้าใช้เพื่อเรียกใช้งานคำสั่งเนื่องจากนั่นคือจิตวิญญาณของการเรียกใช้คำสั่งในบริบท / เชลล์อื่น โดยปกติแล้วเชลล์ที่ไม่มีการโต้ตอบจะไม่มาโดยอัตโนมัติ~/.bashrcซึ่งเกิดขึ้นที่นี่อย่างชัดเจน bashจริง ๆ แล้วพยายามช่วยเราที่นี่ จากเอกสาร

เรียกใช้โดย remote shell daemon

Bash พยายามที่จะกำหนดว่าเมื่อใดที่มันถูกรันด้วยอินพุตมาตรฐานที่เชื่อมต่อกับการเชื่อมต่อเครือข่ายเช่นเดียวกับเมื่อดำเนินการโดย remote shell daemon โดยปกติคือ rshd หรือ secure shell daemon sshd หาก Bash ระบุว่ากำลังรันในโหมดนี้มันจะอ่านและดำเนินการคำสั่งจาก ~ / .bashrc หากไฟล์นั้นมีอยู่และอ่านได้ มันจะไม่ทำเช่นนี้หากถูกเรียกเป็น sh อาจใช้ตัวเลือก --norc เพื่อยับยั้งพฤติกรรมนี้และตัวเลือก --rcfile อาจถูกใช้เพื่อบังคับให้อ่านไฟล์อื่นได้ แต่โดยทั่วไปแล้ว rshd หรือ sshd ไม่เรียกใช้เชลล์ด้วยตัวเลือกเหล่านั้นหรืออนุญาตให้ระบุ


"... มันถูกเรียกใช้งานบนรีโมตโฮสต์แทนที่จะเป็นเชลล์ล็อกอิน" ฉันไม่ได้รับการแบ่งขั้วนี้ คำสั่งถูกเรียกใช้งานบนรีโมตโฮสต์แทนที่จะเป็นล็อกอินเชลล์หรือคำสั่งดำเนินการบนรีโมตโฮสต์แทนที่จะเป็นเชลล์ล็อกอินที่ถูกเรียกใช้งานที่นั่นหรือไม่? ถ้าในอดีตมันเป็นอย่างไร / หรือ? (ไม่ใช่ทั้งสองอย่างปกติเหรอ? ) ถ้าอย่างหลังมันยังคงดำเนินการในบริบทของเชลล์บางเชลล์ใช่ไหม (แบบโต้ตอบที่ไม่ใช่การเข้าสู่ระบบหรือไม่) ดังนั้นคำถามของฉันก็เกี่ยวกับความหมาย - "shell shell" มีความหมายอะไรและทำไม OpenSSH จึงถูกออกแบบมาไม่ให้สร้างคำสั่งเดียว?
Ryan Lue

@RyanLue "รสชาติ" ที่แตกต่างกันของหอยแต่ละตัวทำให้งานบางอย่างง่ายขึ้น / ปลอดภัยมากขึ้น / ปรับให้เหมาะสม ฯลฯ ในขณะที่ทำsshจำเป็นต้องเข้าสู่ระบบผู้ใช้งานตัดสินใจว่าในบางสถานการณ์เช่นขอให้เรียกใช้คำสั่งและกลับมาทำ ไม่ต้องการ / รับประโยชน์จากขั้นตอนพิเศษที่เชลล์ล็อกอินใช้และดังนั้นพวกเขาจึงข้ามไป ดังนั้นจึงมีเชลล์ที่ทำงานอยู่ฉันคิดว่าส่วนใหญ่จะตั้งค่าสภาพแวดล้อมและเนื่องจากเชลล์จะไม่ให้ผู้ใช้ที่เข้าสู่ระบบพวกเขาปฏิบัติต่อราวกับว่าผู้ใช้เพิ่งเริ่มเชลล์ใหม่เพื่อเรียกใช้นั้น คำสั่ง
Eric Renouf

"แน่นอนว่ามีเชลล์ที่รันอยู่ฉันคิดว่าส่วนใหญ่จะตั้งค่าสภาพแวดล้อม ... " <แต่ฉันเพิ่งทดลองกับสิ่งนี้และปรากฏssh <host> <command>ว่าไม่ได้สืบทอดสภาพแวดล้อมของล็อกอินเชลล์ใด ๆ ที่มีอยู่ ตัวอย่างเช่น$ ssh <host> \$PATHส่งคืนเส้นทางตามที่จะเป็นโดยไม่มีการจัดหา.bash_profile(หรือ.profileอย่างที่เคยเป็น) ... ในทางปฏิบัติแล้วทำไมคุณต้องการหลีกเลี่ยงขั้นตอนนั้น
Ryan Lue

“ ... ผู้ใช้งานตัดสินใจว่าในบางสถานการณ์เช่นขอให้ผู้ใช้รันคำสั่งและส่งคืนไม่ต้องการ / รับประโยชน์จากขั้นตอนพิเศษที่เชลล์การล็อกอินใช้และดังนั้นพวกเขาจึงข้ามไป” <เช่นกันโดยเฉพาะการค้นหาคำอธิบาย / ความเข้าใจด้านตัวเลือกการออกแบบนี้ ฉันกำหนดของฉันPATHใน.profile- ไม่ว่าสิ่งที่คุณต้องการโหลดก่อนที่จะใช้คำสั่งโดยพลการในพื้นที่ห่างไกล?
Ryan Lue

1
@RyanLue เซิร์ฟเวอร์ Boks ssh แยกการใช้ ssh ที่แตกต่างกันและสามารถให้สิทธิ์สำหรับแต่ละรายการได้ การเข้าสู่ระบบจากระยะไกล, การดำเนินการทางไกล, การคัดลอกระยะไกล, บางทีนี่อาจช่วยให้เข้าใจว่าทำไมคุณถึงมีพฤติกรรมที่คุณอธิบาย การเข้าสู่ระบบระยะไกล (ใช้แบบโต้ตอบ) อาจจะมากเกินไปที่จะขอในสภาพแวดล้อมที่มีความปลอดภัยสูง Openssh สามารถถูก จำกัด โดยการใช้ rbash / rksh และ 'logout' ใน. bash_profile หรือ chroot
bbaassssiiee

4

เหตุผลของพฤติกรรมนี้โกหกในระดับที่ต่ำกว่าเปลือกหอย: ssh host(ที่ "เข้าสู่ระบบเปลือก" กรณี) ใช้pseudoterminalในพื้นที่ห่างไกลในการสื่อสารระหว่างsshdกระบวนการเซิร์ฟเวอร์และเปลือก; ssh host commandใช้ไพพ์ระหว่างsshdและcommandแทน Pseudoterminals จำเป็นต้องใช้การโต้ตอบของล่ามคำสั่งเช่นเชลล์หรือโหมด " read-eval-print " ของภาษาสคริปต์ พวกมันใช้ฟีเจอร์ที่เป็นมิตรกับมนุษย์มากมายเช่นสามารถแบ็คสเปซมากกว่าการพิมพ์ผิด แต่พวกเขามีค่าใช้จ่ายมากขึ้นและ (ขึ้นอยู่กับการกำหนดค่า) ไม่อนุญาตให้ข้อมูลโดยพลการผ่านไม่มีการแก้ไขดังนั้น SSH หลีกเลี่ยงการใช้พวกเขาเมื่อการโต้ตอบจะไม่เกิดขึ้น

บางครั้งคำสั่งของ SSH / ไม่มีคำสั่งฮิวริสติกก็ผิดพลาด มันสามารถถูกแทนที่ด้วย-tและ-Tสวิตช์ ตัวอย่างเช่นในการเข้าสู่เครื่องระยะไกลและ reattach screenเซสชันที่ถูกระงับทันทีคุณต้องทำssh -t host screen -R; ssh host screen -Rจะทำให้screenบ่นว่าไม่ได้เชื่อมต่อกับเทอร์มินัล ฉันไม่สามารถนึกถึงสถานการณ์เมื่อคุณต้องการใช้งานจริง ๆ-Tแต่ก็มีถ้าคุณเคยเจอ


1

ก่อนอื่นคุณต้องเห็นประเภทที่แตกต่างกันคุณสามารถอ่านสิ่งนี้:

/unix/170493/login-non-login-and-interactive-non-interactive-shells

ตอนนี้ถ้าคุณเปิด bashrc ของคุณคุณจะเห็นจุดเริ่มต้นนี้:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

ซึ่งหมายความว่าขึ้นอยู่กับว่าคุณเข้าถึงระบบไฟล์นี้โหลดโค้ดภายในหรือไม่


ตกลง แต่สิ่งนี้ทำให้เกิดคำถามที่น่าสนใจ: .bashrcอาจถูกเขียนขึ้นเพื่อไม่ให้มีแหล่งที่มาหากมีการเรียกในบริบทที่ไม่มีการโต้ตอบ ( เช่นถ้าไม่มี "พรอมต์คำสั่ง" / $PS1ตัวแปร) แต่ssh <host> <command> ไม่แน่นอนแบบไม่โต้ตอบ ; นั่นคือมันไม่เพิ่มพรอมต์คำสั่ง ดังนั้นทำไม OpenSSH จึงได้รับการออกแบบมาเพื่อสร้าง non-login prompt prompt (หนึ่งที่พยายามหาแหล่งที่มา.bashrc) สำหรับกรณีการเข้าสู่ระบบการใช้งานแบบไม่โต้ตอบ?
Ryan Lue
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.