วิธีการทำให้บริการยูนิกซ์เห็นตัวแปรสภาพแวดล้อม?


52

ฉันได้ตั้งค่าตัวแปรสภาพแวดล้อมของฉันโดยใช้/etc/profile:

export VAR=/home/userhome

ถ้าอย่างนั้นฉันecho $VARก็แสดงให้เห็น/home/userhome

แต่เมื่อฉันใส่การอ้างอิงตัวแปรนี้ลงใน/etc/init.d/servicenameไฟล์มันไม่สามารถหาตัวแปรนี้ เมื่อฉันเรียกservice servicename statusใช้/etc/init.d/servicenameไฟล์ที่มีเนื้อหาดังต่อไปนี้:

case "$1" in
status)    
    cd $VAR/dir
    ;;
esac

มันบอกว่า /dir: No such file or directory

แต่มันใช้งานได้ถ้าฉันวิ่ง/etc/init.d/servicename statusแทนservice servicename status

ฉันจะทำให้ยูนิกซ์เห็นตัวแปรสภาพแวดล้อมได้อย่างไร?


โปรดทราบว่าการเรียกระบบ 5 rcสคริปต์โดยตรงยังไม่ทำงานวิธีบนระบบปฏิบัติการ systemd ว่าเป็นสวดทุกสคริปต์ที่จะกลายเป็นสวดของsystemctlโดยเบ็ดที่ซ่อนอยู่
JdeBP

คำตอบ:


70

ปัญหาคือserviceแถบตัวแปรสภาพแวดล้อมทั้งหมด แต่TERM, PATHและLANGซึ่งเป็นสิ่งที่ดี หากคุณกำลังดำเนินการสคริปต์โดยตรงไม่มีอะไรลบตัวแปรสภาพแวดล้อมเพื่อให้ทุกอย่างทำงาน

คุณไม่ต้องการพึ่งพาตัวแปรสภาพแวดล้อมภายนอกเนื่องจากเมื่อเริ่มต้นอาจไม่พบตัวแปรสภาพแวดล้อมและระบบเริ่มต้นของคุณอาจไม่ได้ตั้งค่าไว้

หากคุณยังต้องการพึ่งพาตัวแปรดังกล่าวให้แหล่งไฟล์และอ่านตัวแปรจากมันเช่นสร้าง/etc/default/servicenameด้วยเนื้อหา:

VAR=value

และแหล่งที่มาจากสคริปต์ init ของคุณเช่น:

[ -f /etc/default/service-name ] && . /etc/default/service-name

if [ -z "$VAR" ] ;  then
  echo "VAR is not set, please set it in /etc/default/service-name" >&2
  exit 1
fi

case "$1" in
status)    
    cd "$VAR"/dir
    ;;
esac

13
มีประโยชน์มากขอบคุณ สำหรับมือใหม่ Linux อื่น ๆ นี่คือข้อมูลลับ Bash [ ... ]เป็นการจดชวเลขสำหรับการทดสอบตามเงื่อนไข ดูคำตอบนี้ -fเป็นifอาร์กิวเมนต์เพื่อตรวจสอบว่ามีไฟล์อยู่หรือไม่ &&เป็นตัวดำเนินการลัดวงจร: ทำเฉพาะคำสั่งที่สองถ้าออกครั้งแรกด้วย 0. .source หรือ dot operator: อ่านและดำเนินการคำสั่งจากอาร์กิวเมนต์ชื่อไฟล์ -zเป็นifอาร์กิวเมนต์เพื่อตรวจสอบสตริงที่มีความยาวเป็นศูนย์ >&2ส่งออกไปยัง stderr ดูยังรู้เบื้องต้นเกี่ยวกับถ้า
Mark Berry

@MarkBerry -fเป็นส่วนหนึ่งของไม่ได้[ if
Chris Down

@ChrisDown ขอบคุณ ดังนั้น " [ ... ]เป็นชื่อย่อสำหรับเงื่อนไขtestคำสั่งดูคำตอบนี้ . -fเป็นtestอาร์กิวเมนต์เพื่อตรวจสอบว่าไฟล์ที่มีอยู่."
Mark Berry

@ Markberry ถูกต้อง คุณสามารถนึกถึง[(หรือtest) เป็นเพียงคำสั่งอื่น - ทั้งหมดifจะดำเนินการบางอย่างตามสถานะการออก
Chris Down

ผมเคยทำงานเป็นสถานการณ์ที่คล้ายกันนี้ แต่ฉันไม่ต้องการ$VARที่จะอยู่ในสคริปต์ init ที่ฉันต้องการให้สามารถใช้ได้กับโปรแกรมที่แตกต่างกัน 2 หรือ 3 สายปลายน้ำของสคริปต์ init เช่น. สคริปต์ init เรียกเริ่มหยุด-ภูตซึ่งเรียกโปรแกรมที่ 1 (Java) ซึ่งเรียกโปรแกรมที่ 2 $VARที่ต้องการ ฉันลองใช้เคล็ดลับในคำตอบนี้ แต่ดูเหมือนจะไม่ทำงานในสถานการณ์ของฉัน ฉันจะมั่นใจได้อย่างไรว่า$VARจะมีให้ในโปรแกรม 2
FrustratedWithFormsDesigner

1

ในกรณีของผมผมจำเป็นต้องมีRAILS_ENVที่ตั้งอยู่ใน:/etc/bash.bashrc export RAILS_ENV=stagingฉันเพิ่ม$(grep RAILS_ENV /etc/bash.bashrc)และนั่นทำให้ตัวแปรพร้อมใช้งานกับสคริปต์ ฉันทำอย่างนี้ฉันจึงไม่ต้องรวมไฟล์ที่เหลือ


-1

ทางออกหนึ่งที่น่าเกลียดที่จะใช้งานได้:

function exec() {
    args=( $@ )
    command=${args[0]}
    dummy=${args[1]}
    whoami=`whoami`
    if [ -z "$dummy" ]; then
        me=`basename $0`
        runuser -l ${whoami} -c "bash /etc/init.d/${me} ${command} dummy"
    else
       printenv
   fi
}

case $1 in
    status)
        status
        ;;
    start|stop|kill|restart)
        exec $*
        ;;
    *)
        usage
esac
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.