ฉันจะตั้งค่าตัวแปรสภาพแวดล้อมบนเซิร์ฟเวอร์ที่เปลี่ยนจากเซสชันเป็นเซสชันได้อย่างไร


92

เมื่อฉันsshเข้าสู่เซิร์ฟเวอร์ฉันจะส่งตัวแปรสภาพแวดล้อมจากไคลเอนต์ไปยังเซิร์ฟเวอร์ได้อย่างไร ตัวแปรสภาพแวดล้อมนี้เปลี่ยนไประหว่างการเรียกใช้ ssh ที่แตกต่างกันดังนั้นฉันไม่ต้องการเขียนทับ$HOME/.ssh2/environmentทุกครั้งที่ฉันทำการเรียก ssh ฉันจะทำสิ่งนี้ได้อย่างไร


2
คำถามของคุณจะต้องเป็น liiittle เฉพาะเจาะจงมากขึ้น
Ignacio Vazquez-Abrams

3
คำถามนี้ชัดเจนสำหรับฉัน อย่างไรก็ตามจากsshหน้า man page ฉันไม่เห็นวิธีการอื่นนอกจากการตั้งค่าตัวแปรด้วยตนเองเมื่อคุณลงชื่อเข้าใช้เซิร์ฟเวอร์เว้นแต่คุณจะแก้ไข ~ / .ssh2 / environment
garyjohn

แต่ละครั้งแตกต่างกันหรือไม่? หรือค่าที่แตกต่างกันอย่างไร
Dennis Williamson


1
วิธีอื่น ๆ เช่นนี้เป็นที่นิยมมากขึ้น ไม่สำคัญว่าเก่ากว่า
kenorb

คำตอบ:


110

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

หากคุณต้องการให้ตัวแปรรับค่าเดียวกันบนเซิร์ฟเวอร์ที่มีในไคลเอนต์ให้ลองSendEnvตัวเลือก:

ssh -o SendEnv = MYVAR server.example.com คำสั่งของฉัน

สิ่งนี้ต้องการการสนับสนุนจากเซิร์ฟเวอร์ ด้วย OpenSSH, /etc/sshd_configชื่อตัวแปรจะต้องมีอำนาจใน

หากเซิร์ฟเวอร์อนุญาตเฉพาะชื่อตัวแปรบางตัวเท่านั้นคุณสามารถแก้ไขได้ ตัวอย่างเช่นการตั้งค่าทั่วไปอนุญาตให้LC_*ทำได้และคุณสามารถทำสิ่งต่อไปนี้:

ssh -o SendEnv = LC_MYVAR server.example.com 'MYVAR = $ LC_MYVAR; ยกเลิกการตั้งค่า LC_MYVAR; ส่งออก MYVAR; mycommand'

หากLC_*ไม่มีตัวเลือกคุณสามารถส่งผ่านข้อมูลในTERMตัวแปรสภาพแวดล้อมซึ่งจะถูกคัดลอกเสมอ (อาจมีการจำกัดความยาว) คุณจะต้องตรวจสอบให้แน่ใจว่ารีโมตเชลล์ไม่ได้ จำกัดTERMตัวแปรเพื่อกำหนดประเภทเทอร์มินัลที่รู้จัก ผ่าน-tตัวเลือกเพื่อ ssh หากคุณไม่ได้เริ่มเปลือกโต้ตอบระยะไกล

env TERM = "ข้อมูลเพิ่มเติม: $ TERM" ssh -t server.example.com 'MYVAR = $ {TERM%: *}; ระยะ = $ {ระยะ ## *:}; ส่งออก MYVAR; mycommand'

ความเป็นไปได้อีกอย่างหนึ่งคือการกำหนดตัวแปรโดยตรงในคำสั่ง:

ssh -t server.example.com 'ส่งออก MYVAR = "ข้อมูลเพิ่มเติม"; mycommand'

ดังนั้นหากผ่านตัวแปรท้องถิ่น:

ssh -t server.example.com 'ส่งออก MYVAR =' "$ LOCALVAR '"'; mycommand'

อย่างไรก็ตามระวังปัญหาการอ้างอิง: ค่าของตัวแปรจะถูกแก้ไขโดยตรงในข้อมูลโค้ดของเชลล์ที่ดำเนินการทางด้านระยะไกล ตัวอย่างสุดท้ายข้างต้นถือว่า$LOCALVARไม่มีคำพูดใด ๆ ( ')


2
ขอบคุณมากฉันโกรธมากที่ตัวแปร LC_ * นั้นถูกส่งออกไปยัง ssh และคำตอบของคุณทำให้ฉันดูที่ไหนดี ฉันต้องปิดการใช้งานใน ~ / .ssh / config
akostadinov

1
ฉันอยู่ในสถานการณ์ของโปสเตอร์ต้นฉบับ แต่ตัวแปรที่ฉันต้องการส่งต่อคือ TERM ดังนั้นฉันจึงสับสนกับคำตอบของคุณ การส่งต่อข้อความอัตโนมัตินี้ถูกปิดการใช้งานโดย OpenSSH เวอร์ชันล่าสุดหรือไม่
Doub

1
@Doub ค่าเริ่มต้นคือการปฏิเสธตัวแปรสภาพแวดล้อมทั้งหมดในฝั่งเซิร์ฟเวอร์โดยมีAcceptEnvคำสั่งsshd_configตามที่ผู้ดูแลระบบต้องการ แต่TERMได้รับการปฏิบัติเป็นพิเศษเท่าที่ฉันรู้ว่าไม่มีทางที่จะกรองมันในฝั่งเซิร์ฟเวอร์ (มันถูกตั้งค่าในสภาพแวดล้อมของเชลล์โดยไม่คำนึงถึงการตั้งค่าใด ๆ ) คุณแน่ใจหรือว่าไม่มีสคริปต์โปรไฟล์แทนที่ ( /etc/profileหรือ~/.profileหรือ~/.bashrc)
Gilles

2
@Gilles: ฉันทดสอบอีกครั้งและถ้าฉันไม่ได้เพิ่ม TERM ในคำสั่ง AcceptEnv ของฉันอย่างชัดเจน TERM จะไม่ถูกส่งต่อไป ฉันไม่ได้เปิดเชลล์ แต่ใช้คำสั่งโดยตรงตัวอย่างเช่น: "ssh -o SendEnv = TERM shell.example.com env" ที่พิมพ์ตัวแปรสภาพแวดล้อมทั้งหมดและ TERM จะปรากฏเฉพาะเมื่ออยู่ใน SendEnv บนไคลเอนต์และ AcceptEnv บนเซิร์ฟเวอร์ ถ้าฉันเรียกใช้ "ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}" พร้อมกับ AcceptEnv หรือ SendEnv มันจะพิมพ์ "โง่" ซึ่งฉันไม่แน่ใจว่ามาจากไหน (env ไม่ได้แม้แต่ รายการ TERM ในกรณีนั้น)
Doub

7
@ คู่โอ้ฉันเข้าใจแล้ว TERMถูกส่งเมื่อไคลเอ็นต์ร้องขอให้เซิร์ฟเวอร์จัดสรร tty TERMหากมีขั้วที่ไม่มีในด้านระยะไกลก็จะไม่มีประโยชน์ที่จะส่ง เมื่อคุณระบุคำสั่งถ้าคุณต้องการที่จะมีขั้วในด้านระยะไกลคุณต้อง-tเลือกบรรทัดคำสั่ง (หรือRequestTTYใน~/.ssh/config)
Gilles

12

หากคุณสามารถจัดการโฮสต์เป้าหมายคุณสามารถกำหนดค่า sshd เพื่ออนุญาตให้ส่งผ่านตัวแปรสภาพแวดล้อมท้องถิ่นของคุณไปยังโฮสต์เป้าหมาย

จากหน้า man sshd_config:

 PermitUserEnvironment
     Specifies whether ~/.ssh/environment and environment= options in
     ~/.ssh/authorized_keys are processed by sshd.  The default is
     "no".  Enabling environment processing may enable users to bypass
     access restrictions in some configurations using mechanisms such
     as LD_PRELOAD.

การกำหนดค่า sshd มักจะอยู่ที่ /etc/ssh/sshd_config


7
มันมีประโยชน์มากที่จะรู้ว่าสิ่งนี้ถูกตั้งค่าเป็น "ไม่" โดยค่าเริ่มต้น!
jathanism

6

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

ssh remote.host my_command

คุณสามารถทำได้:

ssh remote.host env ENV_VAR=$ENV_VAR my_command

"อาจ"? ฉันหวังว่าฉันจะอ่านมันก่อนที่จะลองคำตอบนี้ ไม่ได้ผลสำหรับฉัน
tishma

1
สนใจที่จะอธิบายรายละเอียดข้อผิดพลาดใด ๆ ที่ได้รับหรือไม่?
pioto

1
@pioto อาจอ้างถึงเช่นหาก ENV_VAR มีช่องว่างอยู่
Martin C. Martin

สำหรับ Mac คุณต้องมีตัวเลือก -t สำหรับเวอร์ชันที่มีการโต้ตอบมิฉะนั้นจะติดอยู่ ดังนั้นสิ่งนี้อาจใช้งานได้: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan

3

การตอบสนองของ @ emptyset (ซึ่งไม่ได้ผลสำหรับฉัน) ทำให้ฉันตอบคำถามนี้

คุณสามารถเพิ่มคำสั่งนี้ไปยัง~/.ssh/authorized_keysไฟล์ของคุณ:

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>

export VARIABLE=<something>กำลังออกจากทันทีและการเชื่อมต่อ SSH ถูกปิด (ล็อคฉันออกจากเซิร์ฟเวอร์) ในขณะที่/usr/bin/env ... $SHELLจะเรียกใช้เชลล์เริ่มต้นของคุณด้วยสภาพแวดล้อมที่ปรับเปลี่ยน


นี่แค่แฮงค์เมื่อเข้าสู่ระบบสำหรับฉัน เมื่อฉันลบมัน SSH กลับสู่ปกติและฉันได้รับเปลือกเข้าสู่ระบบตามปกติของฉัน
Nick Sweeting

@NickSweeting คุณเคยลองเปลี่ยน$SHELLด้วยเชลล์จริงหรือเปล่า? ตรวจสอบด้วยว่า / usr / bin / env มีอยู่บนเซิร์ฟเวอร์ อย่างไรก็ตามการแก้ปัญหาไม่สมบูรณ์แบบ: ฉันได้สังเกตว่ามันหยุดเมื่อฉันต้องการใช้scpหรือคำสั่งแบบอินไลน์
madprog

ใช่นั่นเป็นสิ่งแรกที่ฉันลอง แต่น่าเสียดายที่ไม่ได้ไปทำงานลงเอยด้วยการเปิดใช้งานPermitUserEnvironment yesและการใช้แทนenvironment="..." command="..."
Nick Sweeting

มันทำงานได้ดีสำหรับฉัน
นายเทาร

2

ในลูกค้าในพื้นที่ของ~/.ssh/configคุณคุณสามารถเพิ่มSetEnvเช่น

Host myhost
  SetEnv FOO=bar

หมายเหตุ: man ssh_configตรวจสอบ

จากนั้นบนเซิร์ฟเวอร์ตรวจสอบให้แน่ใจว่าไคลเอนต์ส่งผ่านตัวแปรสภาพแวดล้อมบางอย่างใน/etc/ssh/sshd_configไฟล์ปรับแต่งของคุณ:

AcceptEnv LANG LC_* FOO BAR*

หมายเหตุ: man sshd_configตรวจสอบ


1

คุณสามารถลองเรียกใช้คำสั่งที่กำหนดเองโดยสมมติว่าคุณมีการตั้งค่าการล็อกอินแบบ ssh โดยใช้รหัสผ่าน บนเซิร์ฟเวอร์แก้ไขรายการ ~ / .ssh / authorized_keys ของคุณที่สอดคล้องกับคีย์จากไคลเอนต์ของคุณ:

command="export VARIABLE=<something>" ssh-rsa <key>

ดูลิงค์นี้ในส่วนForced Commandเพื่อดูรายละเอียดเพิ่มเติมเล็กน้อย


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

1

ฉันกำลังสร้างบิวด์แบบกำหนดเองของ OpenSSH สำหรับอุปกรณ์ที่มี cramfs ในโฮมไดเร็กตอรี่และ / etc (Cram FS อ่านได้อย่างเดียว) ดังนั้น ~ / .ssh / สภาพแวดล้อมจะไม่ทำงานหากไม่ได้สร้าง FS ขึ้นใหม่ทั้งหมด อุปกรณ์ (ระบบฝังตัวดังนั้นการใช้ CRAMFS) คุณสามารถระบุใน sshd_config ตำแหน่งของไฟล์ authroized_keys แต่ด้วยเหตุผลบางอย่าง environment = ทำงานได้เฉพาะกับตัวแปรสภาพแวดล้อมใน ~ / .ssh / authroized_keys การแก้ไข / etc / profile ไม่ใช่ตัวเลือกและฉันต้องโหลด ssh ในไดเรกทอรีที่ไม่ได้มาตรฐาน ใน session.c หลังจาก child_set_env (... "MAIL" ... ) เพียงแค่เพิ่มตัวแปรสภาพแวดล้อมที่คุณต้องการ (นี่คือแฮ็คที่ฉันรู้ ... ) แต่เพียงแค่ใส่คนที่ต้องการ envs hardcoded สำหรับเซสชันถ้าคุณเป็น รวบรวมจากแหล่งที่คุณสามารถทำได้ TGI-ขัด


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