ฉันได้ประกาศฟังก์ชั่นและตัวแปรใน 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
ฉันได้ประกาศฟังก์ชั่นและตัวแปรใน 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
คำตอบ:
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 /; "true
echo ""; 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 --login
sh
สิ่งนี้ไม่ทำงานเนื่องจากฟังก์ชั่น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 ด้วยตนเอง
ในกรณีของฉันฉันต้องการที่จะผ่านอาร์เรย์และมีปัญหาบางอย่าง แต่ก็ประสบความสำเร็จหลังจากที่ในขณะโดยสะท้อนค่าอาร์เรย์ไปยัง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[@]};
...