การส่งผ่านตัวแปรในคำสั่ง ssh ระยะไกล


105

ฉันต้องการรันคำสั่งจากเครื่องของฉันโดยใช้ ssh และส่งผ่านตัวแปรสภาพแวดล้อม $BUILD_NUMBER

นี่คือสิ่งที่ฉันกำลังพยายาม:

ssh pvt@192.168.1.133 '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER ถูกตั้งค่าบนเครื่องที่ทำการโทร ssh และเนื่องจากตัวแปรไม่มีอยู่บนโฮสต์ระยะไกลจึงไม่ถูกหยิบขึ้นมา

ฉันจะส่งผ่านค่าของ$BUILD_NUMBER?


1
ไม่เกี่ยวข้องกับฮัดสันลบแท็ก (ฮัดสันเพิ่งสร้างตัวแปร)
Peter Schuetze

คำตอบ:


199

ถ้าคุณใช้

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

แทน

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

เชลล์ของคุณจะแก้ไข$BUILD_NUMBERก่อนที่จะส่งสตริงคำสั่งไปยังโฮสต์ระยะไกล


8
หากมีคนต้องใช้เครื่องหมายคำพูดเดี่ยวเพื่อให้คำสั่งที่รวมอยู่ในเครื่องหมายคำพูดนั้นไม่ได้รับการประเมินในเครื่องพวกเขาควรใช้ "'$ VARIABLE'" ตัวอย่าง: ssh pvt@192.168.1.133 '~ / tools / run_pvt.pl "' $ BUILD_NUMBER '"'
dr.doom

3
ไม่ทราบว่า bash ตอบสนองแตกต่างกันกับเครื่องหมายคำพูดเดี่ยวและเครื่องหมายคำพูดคู่ ขอบคุณ!
silgon

1
นักพัฒนาหลักของ linux ต้องมอดไหม้ในนรก
goldstar

@goldstar โปรดทราบว่าความแตกต่างระหว่าง single quote และ double quote behavior ในเชลล์เกิดขึ้นก่อน Linux ภายในหลายทศวรรษ
sarnold

3
PSA: หากสตริงของคุณมีอินพุตของผู้ใช้นี่เป็นความคิดที่แย่มากและอาจเปิดโอกาสให้คุณโจมตีด้วยการแทรกโค้ด
Brian McCutchon

27

ตัวแปรในอัญประกาศเดี่ยวไม่ได้รับการประเมิน ใช้เครื่องหมายคำพูดคู่:

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

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


4

(คำตอบนี้อาจดูซับซ้อนโดยไม่จำเป็น แต่ก็สามารถขยายได้อย่างง่ายดายและมีประสิทธิภาพสำหรับการเว้นวรรคและอักขระพิเศษเท่าที่ฉันรู้)

คุณสามารถป้อนข้อมูลได้โดยตรงผ่านอินพุตมาตรฐานของsshคำสั่งและreadจากตำแหน่งระยะไกล

ในตัวอย่างต่อไปนี้

  1. อาร์เรย์ที่จัดทำดัชนีจะเต็มไปด้วย (เพื่อความสะดวก) พร้อมด้วยชื่อของตัวแปรที่มีค่าที่คุณต้องการดึงข้อมูลทางด้านรีโมต
  2. สำหรับตัวแปรเหล่านั้นแต่ละตัวเรากำหนดให้กับsshบรรทัดที่สิ้นสุดด้วยค่าว่างเพื่อให้ชื่อและค่าของตัวแปร
  3. ในshhคำสั่งเองเราวนซ้ำบรรทัดเหล่านี้เพื่อเริ่มต้นตัวแปรที่ต้องการ
# Initialize examples of variables.
# The first one even contains whitespace and a newline.
readonly FOO=$'apjlljs ailsi \n ajlls\t éjij'
readonly BAR=ygnàgyààynygbjrbjrb

# Make a list of what you want to pass through SSH.
# (The “unset” is just in case someone exported
# an associative array with this name.)
unset -v VAR_NAMES
readonly VAR_NAMES=(
    FOO
    BAR
)

for name in "${VAR_NAMES[@]}"
do
    printf '%s %s\0' "$name" "${!name}"
done | ssh user@somehost.com '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

    # Check
    printf "FOO = [%q]; BAR = [%q]\n" "$FOO" "$BAR"
'

เอาท์พุต:

FOO = [$'apjlljs ailsi \n ajlls\t éjij']; BAR = [ygnàgyààynygbjrbjrb]

หากคุณไม่จำเป็นต้องใช้exportคุณควรใช้declareแทนexportไฟล์.

ฉบับง่ายจริงๆ (ถ้าคุณไม่จำเป็นต้องขยายที่มีตัวแปรเดียวกับกระบวนการอื่น ๆ ) จะมีลักษณะ:

$ ssh user@somehost.com 'read foo' <<< "$foo"

2

รายชื่อของตัวแปรสภาพแวดล้อมที่ได้รับการยอมรับใน SSHD LC_*โดยค่าเริ่มต้นรวมถึง ดังนั้น:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3

1

นอกจากนี้ยังสามารถส่งผ่านตัวแปรสภาพแวดล้อมอย่างชัดเจนผ่าน ssh ต้องมีการตั้งค่าฝั่งเซิร์ฟเวอร์ผ่านดังนั้นนี่จึงไม่ใช่คำตอบที่เป็นสากล

ในกรณีของฉันฉันต้องการส่งคีย์การเข้ารหัสที่เก็บข้อมูลสำรองไปยังคำสั่งบนเซิร์ฟเวอร์หน่วยเก็บข้อมูลสำรองโดยไม่ต้องเก็บคีย์นั้นไว้ที่นั่น แต่โปรดทราบว่าตัวแปรสภาพแวดล้อมใด ๆ สามารถมองเห็นได้ในps! วิธีการส่งคีย์บน stdin ก็ใช้ได้เช่นกัน แต่ฉันพบว่ามันยุ่งยากเกินไป ไม่ว่าในกรณีใดต่อไปนี้เป็นวิธีส่งตัวแปรสภาพแวดล้อมผ่าน ssh:

บนเซิร์ฟเวอร์แก้ไขsshd_configไฟล์โดยทั่วไป/etc/ssh/sshd_configและเพิ่มAcceptEnvคำสั่งที่ตรงกับตัวแปรที่คุณต้องการส่งผ่าน ดูman sshd_config. ในกรณีของฉันฉันต้องการส่งผ่านตัวแปรไปยังการสำรองข้อมูล borg ดังนั้นฉันจึงเลือก:

AcceptEnv BORG_*

ตอนนี้บนไคลเอนต์ใช้-o SendEnvตัวเลือกเพื่อส่งตัวแปรสภาพแวดล้อม บรรทัดคำสั่งต่อไปนี้ตั้งค่าตัวแปรสภาพแวดล้อมBORG_SECRETจากนั้นแฟล็กเพื่อส่งไปยังเครื่องไคลเอ็นต์ (เรียกว่าbackup) จากนั้นจะทำงานที่printenvนั่นและกรองผลลัพธ์สำหรับตัวแปร BORG:

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens

คุณสามารถ "ลักลอบ" ตัวแปรของคุณในการใช้การตั้งค่าด้านเซิร์ฟเวอร์ค่าเริ่มต้นดูคำตอบของฉัน ส่วนสำคัญคือการกำหนดค่า OpenSSHd เริ่มต้นนั้นรวมLC_*เป็นตัวแปรที่อนุญาตให้ส่งดังนั้นเพียงแค่ใช้$LC_TvE_fooหรือ$LC_BORG_SECRETตรวจสอบให้แน่ใจว่าคุณไม่ "ชนกัน" กับตัวแปรในตัว
Alex Stragies

0

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

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

หากคุณต้องการตั้งค่าตัวแปรสภาพแวดล้อมบนโฮสต์ระยะไกลและใช้งานจริงๆคุณสามารถใช้envโปรแกรมได้

ssh pvt@192.168.1.133 "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

ในกรณีนี้เป็นเรื่องที่เกินความจำเป็นเล็กน้อยและโปรดทราบ

  • env BUILD_NUMBER=$BUILD_NUMBER ทำการขยายเมตาบนโลคัลโฮสต์
  • BUILD_NUMBERตัวแปรสภาพแวดล้อมระยะไกลจะถูกใช้โดย
    รีโมตเชลล์

-2

หลีกเลี่ยงตัวแปรเพื่อเข้าถึงตัวแปรนอกเซสชัน ssh: ssh pvt@192.168.1.133 "~ / tools / myScript.pl \ $ BUILD_NUMBER"


2
สิ่งนี้ไม่บรรลุสิ่งที่คำถามกำลังขอ
Patrick Trentin

2
จากจุดเปลือกในมุมมองของเทียบเท่ากับ'$FOO' "\$FOO"คำถามคือ "จะส่งตัวแปรเชลล์ด้วย SSH ได้อย่างไร" ตามที่ระบุไว้แล้วโดย @PatrickTrentin นี่ไม่ใช่คำตอบที่ถูกต้องเนื่องจากBUILD_NUMBERไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อมจากระยะไกล
Gilles Gouaillardet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.