ส่งต่อฟังก์ชันและตัวแปรไปยัง sudo su - <user> << EOF


9

ฉันได้ประกาศฟังก์ชั่นและตัวแปรใน bash / ksh และฉันต้องการส่งต่อไปยังsudo su - {user} << EOF:

#!/bin/bash

log_f() {
echo "LOG line: $@"
}

extVAR="yourName"

sudo su - <user> << EOF
  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

คำตอบ:


4

sudo su -ซึ่งเป็นวิธีที่ซับซ้อนในการเขียนsudo -iสร้างสภาพแวดล้อมที่เก่าแก่ นั่นคือจุดของเปลือกเข้าสู่ระบบ แม้แต่ธรรมดาsudoจะลบตัวแปรส่วนใหญ่ออกจากสภาพแวดล้อม นอกจากนี้ยังsudoเป็นคำสั่งจากภายนอก ไม่มีวิธีในการยกระดับสิทธิ์ในเชลล์สคริปต์เท่านั้นเพื่อรันโปรแกรมภายนอก ( sudo) ด้วยสิทธิ์พิเศษและนั่นหมายถึงตัวแปรเชลล์ใด ๆ (เช่นตัวแปรที่ไม่ได้ถูกเอ็กซ์พอร์ต) และฟังก์ชั่นที่กำหนดในพาเรนต์เชลล์จะไม่สามารถใช้ได้ เปลือกลูก

คุณสามารถส่งผ่านตัวแปรสภาพแวดล้อมโดยไม่ต้องเรียกใช้เชลล์ล็อกอิน ( sudo bashแทนsudo su -หรือsudo -i) และกำหนดค่า sudo เพื่อให้ตัวแปรเหล่านี้ผ่าน (ด้วยDefaults !env_resetหรือDefaults env_keep=…ในsudoersไฟล์) สิ่งนี้จะไม่ช่วยคุณในการใช้งานฟังก์ชั่น (แม้ว่า bash จะมีฟังก์ชั่นการส่งออกฟังก์ชั่น sudo จะบล็อกมัน)

วิธีปกติในการรับฟังก์ชั่นของคุณในเปลือกลูกก็คือการกำหนดไว้ที่นั่น ดูแลข้อความ: ถ้าคุณใช้<<EOFเอกสาร here เนื้อหาของเอกสาร here จะถูกขยายก่อนโดย parent shell และผลลัพธ์ของการขยายตัวนั้นจะกลายเป็นสคริปต์ที่ child shell มองเห็น นั่นคือถ้าคุณเขียน

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

สิ่งนี้แสดงชื่อของผู้ใช้ดั้งเดิมไม่ใช่ผู้ใช้เป้าหมาย เพื่อหลีกเลี่ยงการขยายระยะแรกให้อ้างเครื่องหมายเอกสารที่นี่หลังจาก<<ผู้ดำเนินการ:

sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF

ดังนั้นหากคุณไม่ต้องการส่งผ่านข้อมูลจากพาเรนต์เชลล์ไปยัง child shell คุณสามารถใช้เอกสารที่ยกมาที่นี่:

#!/bin/bash
sudo -u "$target_user" -i  <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF

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

sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF

ผลลัพธ์ของการwhoamiเป็นบิตของรหัสเปลือกไม่ใช่สตริง ตัวอย่างเช่นถ้าwhoamiคำสั่งกลับมาแล้วเปลือกเด็กจะรันคำสั่ง"; rm -rf /; "trueecho ""; rm -rf /; "true"

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

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh  _ "$extVAR" <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

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

#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
  log_f() {
  echo "LOG line: $@"
  }
  intVAR=$(date)
  log_f "${intVAR}" "${1}"
EOF

โปรดทราบว่าถ้าคุณคาดหวัง/etc/profileและผู้ใช้เป้าหมายคือ~/.profileจะอ่านคุณจะต้องอ่านพวกเขาอย่างชัดเจนหรือโทรแทนbash --loginsh


1

สิ่งนี้ไม่ทำงานเนื่องจากฟังก์ชั่นlog_fไม่ได้ประกาศในsudo su -เชลล์ที่คุณเปิดใช้ แทน:

extVAR="yourName"

sudo su - <user> << EOF

log_f() {
echo "LOG line: $@"
}

  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

คุณต้องรับฟังก์ชั่นที่กำหนดในรูตย่อยของรูท อาจทำได้ แต่ .... ฉันไม่รู้ว่าส่วนใหญ่ของสิ่งนั้นทำอะไร อย่างน้อย - ตราบใดที่ค่าsudoมิได้suความต้องการ stdin อ่านรหัสผ่าน - ที่ควรจะได้รับlog_f()การประกาศ

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


1

ในกรณีของฉันฉันต้องการที่จะผ่านอาร์เรย์และมีปัญหาบางอย่าง แต่ก็ประสบความสำเร็จหลังจากที่ในขณะโดยสะท้อนค่าอาร์เรย์ไปยังenv-key และห่อรหัสตั้งใจในและพื้นมีมันสร้างอาร์เรย์เช่นbash -c '<intended code>' .:INNER_KEY=($<env_key>)

สำหรับการสอบ:

#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
  bash -c '
    FOO=($PLUGINS);
    echo values: \[${FOO[@]}\];

    for pl in ${FOO[@]};
      do echo value: $pl;
    done;
  '
EOF

ปัญหาคือฉันไม่สามารถทำสิ่งต่อไปนี้โดยตรง (ไม่ได้ใช้bash -c '...'):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.