ทำไม $ PATH ของคำสั่งรีโมต ssh แตกต่างจากเชลล์เชิงโต้ตอบ?


20

ฉันมีผู้ใช้ที่ไม่ได้ทำการแก้ไข $ PATH ในไฟล์ dot ใด ๆ : มันเป็นการตั้งค่าเริ่มต้นของระบบ จากเชลล์ล็อกอิน:

$ ssh example.com
user@example.com:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$SHELL"
echo "$PATH"

user@example.com:~$ /tmp/hello.hs
/bin/bash
/usr/local/bin:/usr/bin:/bin

/etc/profileตรงตามที่ระบุไว้ใน ฉันพบสิ่งนี้ค่อนข้างคาดไม่ถึง:

$ ssh example.com '/tmp/hello.sh'
/bin/bash       
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

เช่นฉันกล่าวว่ามีการปรับเปลี่ยนของ $ PATH ไม่มีหรือใน~/.bashrc /etc/bash.bashrcไม่~/.ssh/environmentเหมือนกัน ssh(1)บอกว่าตัวแปรสภาพแวดล้อมPATHเป็น

ตั้งค่าเป็นเส้นทางเริ่มต้นตามที่ระบุไว้เมื่อรวบรวม ssh

แต่กระทู้นี้จาก StackOverflow และบทความรายชื่อผู้รับจดหมายนี้แนะนำว่าฉันควรจะสามารถมีอิทธิพลต่อ $ PATH สำหรับคำสั่งที่กำหนดเพียงแค่แก้ไข / etc / profile หนึ่งในไฟล์เริ่มต้นเชลล์ ฯลฯ

เกิดอะไรขึ้นที่นี่?

คำตอบ:


16

จากssh(1)หน้าคู่มือ: "หากระบุคำสั่งคำสั่งจะถูกดำเนินการบนรีโมตโฮสต์แทนเชลล์ล็อกอิน"

ดังนั้นในระยะสั้นเมื่อคุณเข้าสู่ระบบทุบตีเครื่องจริงเริ่มต้นเป็นเปลือกเข้าสู่ระบบและโหลดไฟล์ apropriate เมื่อคุณเชื่อมต่อจากระยะไกลและออกคำสั่งมันทำงานในสถานที่ทุบตีซึ่งหมายความว่าไฟล์เหล่านี้ไม่โหลด คุณสามารถแก้ไขได้ด้วยการใช้su -l -cหรือคล้ายกันในส่วนคำสั่งของ ssh

ในบางกรณีฉันเคยเห็น-tข้อโต้แย้งในการทำงานของ SSH (จัดสรร TTY) เช่นกัน

แก้ไข 1 :
ฉันคิดว่าข้อมูล PATH ที่คุณพบว่าเส้นทางเริ่มต้น (ยกเว้นว่าเราแทนที่) เป็นข้อมูลที่รวบรวมไว้ใน sshd ฉันทำให้แน่ใจว่า / etc / profile, / etc / bash *, dotfiles ในพื้นที่ ฯลฯ ไม่มีข้อมูล PATH ในนั้นจากนั้นฉันเข้าสู่ระบบและยังคงมี PATH ฉันค้นหาสิ่งนี้ใน sshd และพบว่ามี ดังนั้นวิธี manpage พูดว่า:

ahnberg@remote$ strings /usr/sbin/sshd | grep -i x11 | grep bin
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

จากนั้นฉันเพิ่มลงPATH=$PATH:/my/testใน.bashrcไฟล์บนรีโมตและตรวจสอบอีกครั้ง:

ahnberg@local$ ssh ahnberg@remote "env | grep PATH"
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/my/test

ดังนั้นฉันสามารถมีอิทธิพลต่อมันอย่างแน่นอนและค่าเริ่มต้นของเส้นทางคือคอมไพล์เป็น sshd :)


อืมวลีที่ว่า "ดำเนินการบนรีโมตโฮสต์" นั้นมีความหมายมากกว่าที่ฉันพูด บิตที่น่าสนใจยิ่งขึ้นซึ่งฉันพลาดไปก่อนหน้านี้มาในส่วน 'สภาพแวดล้อม' ของ manpage เดียวกัน: "PATH ตั้งค่าเป็น PATH เริ่มต้นตามที่ระบุเมื่อรวบรวม ssh" ยกเว้นสิ่งนี้ชี้ให้เห็นว่าฉันควรจะสามารถมีอิทธิพลต่อเส้นทางของคำสั่ง
troutwine

ประเด็นก็คือไม่ใช่เชลล์ล็อกอินดังนั้นจึงไม่เรียกใช้ / source / รวมไฟล์เริ่มต้นเช่นเดียวกับเชลล์ล็อกอินดังนั้นคำแนะนำของฉันจึงควรลอง การใส่สิ่งต่าง ๆ เข้าด้วย.bashrcอาจใช้งานได้ แต่โดยรวมแล้วฉันจะแก้ไขหาก PATH มีความสำคัญ หรือทำไมไม่เพียง แต่ระบุชื่อพา ธ แบบเต็มหากคุณต้องการใช้ 'คำสั่ง' เพื่อเรียกใช้ ssh? :)
Mattias Ahnberg

ฉันแก้ไขโพสต์ของฉันเล็กน้อย ขณะนี้มีเชลล์ล็อกอิน, เชลล์ที่ไม่ใช่ล็อกอินและตัวแปรแบบโต้ตอบ / ไม่โต้ตอบดังกล่าว คำสั่ง SSH ถูกเรียกใช้ในเชลล์ของผู้ใช้ในรูปแบบที่ไม่ใช่การล็อกอินแบบไม่โต้ตอบ bash(1)ภาวนาแสดงให้เห็นว่าไม่มีแฟ้มเริ่มต้นที่จะอ่านในแฟชั่นนี้ แต่ฉันไม่สามารถหาเอกสารเกี่ยวกับวิธี SSH จะอัญเชิญเปลือก ดูเหมือนว่าจะตรงกันข้ามกับแหล่งที่มาที่เชื่อมโยงข้างต้นยกเว้นว่าคนอื่นมีไฟล์เริ่มต้น / etc / ssh / sshrc ที่ฉันไม่มี (มีวิธีแก้ไขปัญหาแน่นอน แต่ประเด็นคือเข้าใจว่า Debian SSHD จัดการเส้นทางโดยค่าเริ่มต้นได้อย่างไร)
troutwine

หากฉันแก้ไข PATH ใน/etc/profileการอัพเดทพา ธ บ็อกซ์ระยะไกลสำหรับฉันดังนั้นssh user@remotebox 'env'แสดง PATH ที่ได้รับการปรับปรุงให้ฉัน เดียวกันจะไปถ้าผมเพิ่มexport PATH=$PATH:/my/testpathไป .bashrc ( แต่ในกรณีของฉันในด้านบนของไฟล์ก่อนที่จะตรวจสอบหอยโต้ตอบ ( -z "$PS1").
แม็ทเทีย Ahnberg

อัปเดตด้วยการทดสอบ / การค้นพบของฉัน
Mattias Ahnberg

3

ฉันสามารถรับ ssh เพื่อเรียกใช้คำสั่งโดยใช้เส้นทางระยะไกลโดยการเรียกใช้:

ssh dist@d6 "bash --login -c 'env'"

env ที่นี่สามารถถูกแทนที่ด้วยคำสั่งที่คุณต้องการ

ฉันมีกุญแจที่ได้รับอนุญาตดังนั้นไม่จำเป็นต้องใช้รหัสผ่านเพื่อเรียกใช้คำสั่งหรือ ssh


3

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

นี่คือเนื้อหาของ/etc/profile.d/ssh_login.sh:

#!/bin/sh
if [ "$SSH_CONNECTION" ]; then
    echo "User '$USER' logged in from '${SSH_CONNECTION%% *}'"
    . /etc/environment
fi

ใช้dropbearแทนopenssh-server(ซึ่งควรทำงานกับ openssh) ตัวแปร SSH_CONNECTION จะถูกตั้งค่าโดยอัตโนมัติเมื่อฉันล็อกอินจากระยะไกล ฉันสร้างการกำหนดค่าโปรไฟล์เปลือกใหม่เพื่อตรวจหาการเข้าสู่ระบบ SSH แสดงข้อมูลบางอย่างบนหน้าจอและที่สำคัญที่สุดคือโหลดการตั้งค่าสภาพแวดล้อมโลกจาก/etc/environmentเพื่อแทนที่ค่าที่รวบรวมไว้ โปรดทราบว่าสิ่งนี้มีผลเฉพาะกับเชลล์ SSH แบบโต้ตอบไม่ใช่การดำเนินการคำสั่งจากระยะไกล

อีกทางเลือกหนึ่งถ้าคุณใช้ openssh และต้องการโหลดสภาพแวดล้อมแบบโกลบอลเสมอไม่ว่าจะเป็นเชลล์แบบโต้ตอบหรือไม่คุณสามารถวาง symlink ใน~/.ssh/ลักษณะนี้:

ln -s /etc/environment ~/.ssh/environment

แล้วคุณจะต้องเปิดใช้งานตัวเลือกในPermitUserEnvironment /etc/sshd/sshd_configทำสิ่งนี้สำหรับผู้ใช้ที่ไว้วางใจเท่านั้นเนื่องจากจะทำให้ผู้ใช้สามารถข้ามข้อ จำกัด การเข้าถึงในการกำหนดค่าบางอย่างโดยใช้กลไกเช่น LD_PRELOAD โปรดดูman sshd_configข้อมูลเพิ่มเติมโดยเฉพาะวิธีการใช้Matchบล็อกเพื่อ จำกัด ตัวเลือกสำหรับผู้ใช้ / กลุ่มเฉพาะ


0

หากคุณต้องการโหลดเส้นทางโปรไฟล์ลอง:

#!/bin/bash -i

ที่ด้านบนของสคริปต์ วิธีนั้นเชลล์อยู่ในโหมดโต้ตอบเมื่อรันสคริปต์

เมื่อ bash ถูกเรียกใช้เป็นเชลล์ล็อกอินแบบโต้ตอบหรือเป็นเชลล์ที่ไม่มีการโต้ตอบกับตัวเลือก --login มันจะอ่านและเรียกใช้คำสั่งจากไฟล์ / etc / profile ก่อนหากไฟล์นั้นมีอยู่ หลังจากอ่านไฟล์นั้นจะค้นหา ~ / .bash_profile, ~ / .bash_login และ ~ / .profile ตามลำดับและอ่านและเรียกใช้คำสั่งจากไฟล์แรกที่มีอยู่และอ่านได้ ตัวเลือก - noprofile อาจถูกใช้เมื่อเชลล์เริ่มต้นเพื่อยับยั้งพฤติกรรมนี้

http://linux.die.net/man/1/bash

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