ตั้งค่าตัวแปรสภาพแวดล้อมจากไฟล์ของคู่คีย์ / ค่า


511

TL; DR:ฉันจะส่งออกชุดของคู่คีย์ / ค่าจากไฟล์ข้อความไปยังสภาพแวดล้อมของเชลล์ได้อย่างไร


สำหรับบันทึกด้านล่างเป็นคำถามต้นฉบับพร้อมตัวอย่าง

ฉันกำลังเขียนสคริปต์ใน bash ซึ่งแยกวิเคราะห์ไฟล์ด้วย 3 ตัวแปรในโฟลเดอร์หนึ่งนี่คือหนึ่งในนั้น:

MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"

ไฟล์นี้ถูกเก็บไว้ใน. /conf/prac1

สคริปต์ minientrega.sh ของฉันแยกวิเคราะห์ไฟล์โดยใช้รหัสนี้:

cat ./conf/$1 | while read line; do
    export $line
done

แต่เมื่อฉันรันminientrega.sh prac1ในบรรทัดคำสั่งมันไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อม

ฉันลองใช้ด้วยsource ./conf/$1แต่ปัญหาเดิมยังคงมีอยู่

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



เหมือนกันกับทับทิม: stackoverflow.com/questions/2139080/… , อัญมณีที่ทำ: github.com/bkeepers/dotenv
Ciro Santilli 郝海东冠状冠状病六四事件法轮功

นี่เป็นคำถามที่ดี แต่เป็นคำพูดที่เจาะจงเกินไปโดยเฉพาะกับชื่อตัวแปรเฉพาะ ("MINIENTREGA_FECHALIMITE" หมายความว่าอย่างไร) และตัวเลข (3) คำถามทั่วไปก็คือ "ฉันจะส่งออกชุดของคีย์ / ค่าคู่จากไฟล์ข้อความไปยังสภาพแวดล้อมของเชลล์" ได้อย่างไร
Dan Dascalescu

นอกจากนี้ยังได้รับคำตอบในunix.SEและมีเนื้อหาเพิ่มเติมในหัวข้อนั้น
Dan Dascalescu

คำตอบ:


208

ปัญหาเกี่ยวกับวิธีการของคุณเป็นexportในwhileวงที่เกิดขึ้นในเปลือกย่อยและตัวแปรเหล่านั้นจะไม่สามารถใช้ได้ในเปลือกปัจจุบัน (แม่ของเปลือกในขณะที่วง)

เพิ่มexportคำสั่งในไฟล์เอง:

export MINIENTREGA_FECHALIMITE="2011-03-31"
export MINIENTREGA_FICHEROS="informe.txt programa.c"
export MINIENTREGA_DESTINO="./destino/entrega-prac1"

จากนั้นคุณต้องระบุแหล่งที่มาในไฟล์ในเชลล์ปัจจุบันโดยใช้:

. ./conf/prac1

หรือ

source ./conf/prac1

4
แม้ว่าการอ่านไฟล์บรรทัดโดยบรรทัดและผ่านแต่ละบรรทัดจะไม่เหมาะปัญหายังสามารถได้รับการแก้ไขโดยเพียงแค่ใช้การเปลี่ยนเส้นทางการป้อนข้อมูลในวง:export while read line; do ... ; done < ./conf/$1
chepner

4
และถ้ามันไม่ได้มาจากไฟล์ให้ใช้< <(commands that generate output)
o11c

5
คุณมีวิธีแก้ปัญหาที่สะอาดกว่านี้ฉันชอบset -o allexport
heralight

2
หากใช้ไฟล์. env นี้ระหว่างระบบการแทรกexportจะทำให้ไฟล์เสียหายสำหรับสิ่งต่าง ๆ เช่น Java, SystemD หรือเครื่องมืออื่น ๆ
FilBot3

1
awk '{print "export " $0}' envfileคำสั่งอำนวยความสะดวกในการผนวกรวมการส่งออกไปยังจุดเริ่มต้นของทุกบรรทัด
Shardj

887

สิ่งนี้อาจมีประโยชน์:

export $(cat .env | xargs) && rails c

เหตุผลที่ฉันใช้นี่คือถ้าฉันต้องการทดสอบ.envสิ่งต่าง ๆ ในคอนโซลทางรถไฟของฉัน

กาเบรียลขึ้นมาด้วยวิธีที่ดีในการรักษาตัวแปรท้องถิ่น วิธีนี้จะช่วยแก้ปัญหาที่อาจเกิดขึ้นเมื่อไปจากโครงการหนึ่งไปอีกโครงการหนึ่ง

env $(cat .env | xargs) rails

ฉันได้ทำการทดสอบกับ bash 3.2.51(1)-release


ปรับปรุง:

หากต้องการละเว้นบรรทัดที่ขึ้นต้นด้วย#ให้ใช้สิ่งนี้ (ขอบคุณความคิดเห็นของ Pete ):

export $(grep -v '^#' .env | xargs)

และถ้าคุณต้องการunsetตัวแปรทั้งหมดที่กำหนดไว้ในไฟล์ใช้สิ่งนี้:

unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs)

ปรับปรุง:

ในการจัดการค่าด้วยช่องว่างให้ใช้:

export $(grep -v '^#' .env | xargs -d '\n')

บนระบบ GNU - หรือ:

export $(grep -v '^#' .env | xargs -0)

บนระบบ BSD


6
ขอบคุณฉันชอบที่นี่ไม่จำเป็นต้องมีอะไรเพิ่มเติมไปยังไฟล์ - ช่วยให้เข้ากันได้กับรูปแบบ Foreman (Procfile) .env
natevw

29
ฉันมาด้วยวิธีการแก้ปัญหา: env $ (cat .env | xargs) ทางรถไฟ
gabrielf

4
ดูเหมือนว่าจะไม่ทำงานหากค่า env ใด ๆ มีช่องว่าง แต่ฉันไม่แน่ใจว่าวิธีที่ดีที่สุด / ที่ต้องการในการระบุค่าด้วยช่องว่างคืออะไร github.com/ddollar/foreman/issues/56กล่าวว่าควรใช้งานได้export $(cat .env)แต่ฉันไม่รู้วิธีจัดการกับช่องว่าง
Dan Benamy

6
@BenjaminWheeler GNU linux มี-dการตั้งค่าตัวคั่นดังนั้นฉันพยายามenv $(cat .env | xargs -d '\n') railsแต่ก็ยังคงมีข้อผิดพลาดกับไฟล์ที่ไม่พบว่า.envมีช่องว่าง ความคิดใด ๆ ที่ว่าทำไมมันถึงใช้งานไม่ได้?
Bailey Parker

19
นี่เป็นรูปแบบที่สั้นกว่าeval $(cat .env) rails
นาลัง

412

-o allexportเปิดใช้งานการนิยามตัวแปรต่อไปนี้ทั้งหมดเพื่อส่งออก +o allexportปิดใช้งานคุณสมบัตินี้

set -o allexport
source conf-file
set +o allexport

9
ทำงานเหมือนจับใจ! แม้ว่า.envไฟล์จะมีความคิดเห็นอยู่ก็ตาม ขอบคุณ!
Slava Fomin II

9
และในหนึ่งบรรทัดset -o allexport; source conf-file; set +o allexport
HarlemSquirrel

1
นี่เป็นวิธีที่ดีในการอ่านในไฟล์คุณสมบัติเมื่อปลั๊กอิน Jenkins EnvInject ไม่ทำงาน ขอบคุณ!
Teresa Peters

21
@CMCDragonkai สำหรับ POSIX set -a; . conf-file; set +aก็จะ
ชาร์ลส์ดัฟฟี่

3
วิธีนี้ใช้ได้ถ้าตัวแปรสภาพแวดล้อมมีช่องว่างอยู่ หลายคนไม่ทำ ในขณะที่วิธี eval () ไม่ฉันก็
แปลก

138
set -a
. ./env.txt
set +a

ถ้า env.txtเป็นเช่น:

VAR1=1
VAR2=2
VAR3=3
...

คำอธิบาย - a เทียบเท่ากับallexport allexportกล่าวอีกนัยหนึ่งการกำหนดตัวแปรทั้งหมดในเชลล์จะถูกส่งออกไปยังสภาพแวดล้อม (ที่จะใช้โดยกระบวนการลูกหลายกระบวนการ) ข้อมูลเพิ่มเติมสามารถพบได้ในเอกสารประกอบการตั้งค่าภายใน :

-a     แต่ละตัวแปรหรือฟังก์ชั่นที่สร้างหรือแก้ไขจะได้รับคุณลักษณะการส่งออกและทำเครื่องหมายเพื่อส่งออกไปยังสภาพแวดล้อมของคำสั่งที่ตามมา

การใช้ '+' แทน '-' ทำให้ตัวเลือกเหล่านี้ถูกปิด ตัวเลือกสามารถใช้เมื่อเรียกใช้เชลล์ ชุดตัวเลือกปัจจุบันอาจพบได้ใน $ -


คุณสามารถอธิบาย -a และ + a ได้ไหม?
อ็อตโต

11
@Otto เทียบเท่ากับ-a allexportกล่าวอีกนัยหนึ่งการกำหนดตัวแปรทุกตัวในเชลล์นั้นจะถูกนำexportไปไว้ในสภาพแวดล้อม (จะถูกใช้โดยกระบวนการลูกหลายกระบวนการ) ดูบทความนี้gnu.org/software/bash/manual/html_node/The-Set-Builtin.html ด้วย
Dan Kowalczyk

33

allexportตัวเลือกที่ถูกกล่าวถึงในสองสามคำตอบอื่น ๆ ที่นี่ซึ่งset -aเป็นทางลัด การจัดหา. env ดีกว่าการวนลูปมากกว่าบรรทัดและส่งออกเนื่องจากอนุญาตให้ใส่ข้อคิดเห็นบรรทัดว่างเปล่าและแม้แต่ตัวแปรสภาวะแวดล้อมที่สร้างโดยคำสั่ง . bashrc ของฉันรวมถึงสิ่งต่อไปนี้:

# .env loading in the shell
dotenv () {
  set -a
  [ -f .env ] && . .env
  set +a
}

# Run dotenv on login
dotenv

# Run dotenv on every new directory
cd () {
  builtin cd $@
  dotenv
}

3
สิ่งนี้ดูดี แต่คุณยกเลิกการโหลดตัวแปรสภาพแวดล้อมเมื่อคุณออกจากไดเรกทอรีหรือไม่
Bastian Venthur

1
ฉันไม่ได้ตั้งค่าตัวแปรและมันไม่เคยมีปัญหา ปพลิเคชันของฉันมักจะใช้ชื่อตัวแปรที่มีความแตกต่างกันและถ้ามีการทับซ้อนฉันจะตั้งค่าให้ว่างใน .env VAR=ว่า
gsf

26
eval $(cat .env | sed 's/^/export /')

1
การใช้eval $(cat .env | sed 's/^[^$]/export /')ช่วยให้คุณมีบรรทัดว่างเพื่อให้อ่านง่ายขึ้น
Mario Uher

2
ฉันพบว่าcat .env | sed 's/^[^$]/export /'ตัดอักขระตัวแรกออก นั่นคือไฟล์ที่A=foo\nB=bar\nฉันได้รับ นี้ทำงานได้ดีกว่าสำหรับการกระโดดข้ามบรรทัดว่าง:export =foo\nexport =bar\n cat .env | sed '/^$/! s/^/export /'
Owen S.

(ฉันยังทราบเพื่อประโยชน์ของนักกอล์ฟรหัส UNIX ที่คุณไม่ต้องการcatในทั้งสองกรณี: eval $(sed 's/^/export /' .env)ทำงานได้เช่นกัน)
โอเวนเอส.

21

ฉันพบวิธีที่มีประสิทธิภาพมากที่สุดคือ:

export $(xargs < .env)

คำอธิบาย

เมื่อเรามี.envไฟล์เช่นนี้:

key=val
foo=bar

วิ่งxargs < .envจะได้รับkey=val foo=bar

ดังนั้นเราจะได้รับexport key=val foo=barและเป็นสิ่งที่เราต้องการ!

การ จำกัด

  1. ไม่จัดการกรณีที่ค่ามีช่องว่างในพวกเขา คำสั่งเช่น env สร้างรูปแบบนี้ - @Shardj

3
ไม่จัดการกรณีที่ค่ามีช่องว่างในพวกเขา คำสั่งเช่นenvสร้างรูปแบบนี้
Shardj

19

นี่คือsedวิธีแก้ไขปัญหาอื่นซึ่งไม่ได้เรียกใช้การประเมินหรือต้องการทับทิม:

source <(sed -E -n 's/[^#]+/export &/ p' ~/.env)

สิ่งนี้จะเพิ่มการส่งออกโดยเก็บความคิดเห็นไว้ในบรรทัดที่ขึ้นต้นด้วยความคิดเห็น

เนื้อหา. env

A=1
#B=2

เรียกใช้ตัวอย่าง

$ sed -E -n 's/[^#]+/export &/ p' ~/.env
export A=1
#export B=2

ฉันพบนี้มีประโยชน์โดยเฉพาะอย่างยิ่งเมื่อสร้างไฟล์ดังกล่าวสำหรับการโหลดในแฟ้มหน่วย systemd EnvironmentFileด้วย


ไม่สนับสนุนหลายบรรทัดใน OSX
Abdennour TOUMI

17

ฉันตอบคำตอบของผู้ใช้ 4040650 upvoted เพราะทั้งง่ายและอนุญาตความคิดเห็นในไฟล์ (เช่นบรรทัดที่ขึ้นต้นด้วย #) ซึ่งเป็นที่ต้องการอย่างมากสำหรับฉันเนื่องจากความคิดเห็นที่อธิบายตัวแปรสามารถเพิ่มได้ เพียงเขียนใหม่ในบริบทของคำถามเดิม

หากสคริปต์ถูกเรียกตามที่ระบุ: minientrega.sh prac1ดังนั้น minientrega.sh อาจมี:

set -a # export all variables created next
source $1
set +a # stop exporting

# test that it works
echo "Ficheros: $MINIENTREGA_FICHEROS"

ต่อไปนี้เป็นข้อมูลที่แยกออกมาจากเอกสารชุด :

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

ตั้ง [--abefhkmnptuvxBCEHPT] [-o ตัวเลือกชื่อ] [อาร์กิวเมนต์ ... ] ตั้ง [+ abefhkmnptuvxBCEHPT] [+ o ตัวเลือกชื่อ] [อาร์กิวเมนต์ ... ]

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

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

-a แต่ละตัวแปรหรือฟังก์ชั่นที่สร้างหรือแก้ไขจะได้รับคุณลักษณะการส่งออกและทำเครื่องหมายเพื่อส่งออกไปยังสภาพแวดล้อมของคำสั่งที่ตามมา

และสิ่งนี้เช่นกัน:

การใช้ '+' แทน '-' ทำให้ตัวเลือกเหล่านี้ถูกปิด ตัวเลือกสามารถใช้เมื่อเรียกใช้เชลล์ ชุดตัวเลือกปัจจุบันอาจพบได้ใน $ -


14

ปรับปรุงคำตอบของสิลาสพอล

การส่งออกตัวแปรบนเชลล์ย่อยทำให้เป็นโลคัลกับคำสั่ง

(export $(cat .env | xargs) && rails c)


จากนั้นคุณสามารถใช้สิ่งนี้(set -a; source dev.env; set +a; rails c)เพื่อให้ได้ประโยชน์จากการจัดหา (เช่นสคริปต์สามารถดำเนินการได้)
Wacha

12

SAVE=$(set +o | grep allexport) && set -o allexport && . .env; eval "$SAVE"

สิ่งนี้จะบันทึก / กู้คืนตัวเลือกดั้งเดิมของคุณไม่ว่าจะเป็นอะไรก็ตาม

การใช้set -o allexportมีข้อดีของการข้ามความคิดเห็นอย่างถูกต้องโดยไม่มี regex

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


2
ฉันอาจexec env -i bashจะล้างสภาพแวดล้อมที่มีอยู่ก่อนที่จะโทรevalถ้าคุณต้องการยกเลิกการตั้งค่าตัวแปรที่ตั้งอยู่ภายใน.envเท่านั้น
b4hand

11

วิธีที่สั้นที่สุดที่ฉันพบ:

.envไฟล์ของคุณ:

VARIABLE_NAME="A_VALUE"

จากนั้นเพียงแค่

. ./.env && echo ${VARIABLE_NAME}

โบนัส: เพราะมันเป็นซับในแบบสั้นจึงมีประโยชน์มากในpackage.jsonไฟล์

  "scripts": {
    "echo:variable": ". ./.env && echo ${VARIABLE_NAME}"
  }

ถ้าคุณมีตัวแปรมากมาย
Madeo

@Madeo คุณสามารถเพิ่มจำนวนบรรทัดได้มากเท่าที่คุณต้องการเช่นเดียวกับบรรทัดVARIABLE_NAME="A_VALUE"
Flavien Volken

9

เรียบง่าย:

  1. คว้าเนื้อหาของไฟล์
  2. ลบบรรทัดว่างใด ๆ (เพียงกรณีที่คุณแยกบางสิ่ง)
  3. ลบความคิดเห็นใด ๆ (เพียงใส่ในกรณีที่คุณเพิ่ม ... )
  4. เพิ่มexportในทุกบรรทัด
  5. eval สิ่งทั้งหมด

eval $(cat .env | sed -e /^$/d -e /^#/d -e 's/^/export /')

ตัวเลือกอื่น (คุณไม่ต้องเรียกใช้eval(ขอบคุณ @Jaydeep)):

export $(cat .env | sed -e /^$/d -e /^#/d | xargs)

สุดท้ายถ้าคุณต้องการทำให้ชีวิตของคุณง่ายขึ้นให้เพิ่มสิ่งนี้ลงใน~/.bash_profile:

function source_envfile() { export $(cat $1 | sed -e /^$/d -e /^#/d | xargs); }

(ทำให้แน่ใจว่าคุณโหลดการตั้งค่า BASH ของคุณ !!! source ~/.bash_profileหรือ .. เพียงสร้างแท็บ / หน้าต่างใหม่และแก้ไขปัญหา) คุณเรียกมันว่า:source_envfile .env


2
ฉันต้องอ่าน. env ข้อความจากตัวแปรลับ gitlab สำหรับไปป์ไลน์: ตามคำสั่งของคุณคำสั่งนี้ใช้ได้ผลสำหรับฉัน: source <( echo $(sed -E -n 's/[^#]+/ &/ p' <(echo "${2}" | tr -d '\r')) );. อย่างใด gitlab tr -d '\r'บันทึกตัวแปรลับกับหน้าต่างกลับรถเพื่อให้ฉันได้ตัดกับ
metanerd

6

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

. ./minientrega.sh

นอกจากนี้ยังอาจมีปัญหาเกี่ยวกับcat | while readวิธีการ while read line; do .... done < $FILEฉันจะแนะนำให้ใช้วิธีการ

นี่คือตัวอย่างการทำงาน:

> cat test.conf
VARIABLE_TMP1=some_value

> cat run_test.sh
#/bin/bash
while read line; do export "$line";
done < test.conf
echo "done"

> . ./run_test.sh
done

> echo $VARIABLE_TMP1
some_value

ต่างจากคำตอบอื่น ๆ ส่วนใหญ่โซลูชันนี้ไม่ได้test.confเป็นไฟล์สคริปต์ นั่นทำให้ดีขึ้น มันปลอดภัยกว่าที่จะไม่อนุญาตให้ใช้สคริปต์เว้นแต่คุณจะต้องการมันจริงๆโดยเฉพาะอย่างยิ่งหากมีคนไม่ทราบว่าเกิดอะไรขึ้น (หรือลืม)
meustrus

5

สร้างคำตอบอื่น ๆ ต่อไปนี้เป็นวิธีการส่งออกเฉพาะส่วนย่อยของบรรทัดในไฟล์รวมถึงค่าที่มีช่องว่างเช่นPREFIX_ONE="a word":

set -a
. <(grep '^[ ]*PREFIX_' conf-file)
set +a

5

นี่คือตัวแปรของฉัน:

  with_env() {
    (set -a && . ./.env && "$@")
  }

เปรียบเทียบกับโซลูชันก่อนหน้า:

  • มันไม่รั่วไหลตัวแปรนอกขอบเขต (ค่าจาก.envไม่ได้สัมผัสกับผู้โทร)
  • ไม่ปิดบังsetตัวเลือก
  • ส่งคืนรหัสทางออกของคำสั่งที่ดำเนินการ
  • ใช้ posix เข้ากันได้ set -a
  • ใช้.แทนsourceเพื่อหลีกเลี่ยงการ bashism
  • คำสั่งไม่ถูกเรียกใช้หากการ.envโหลดล้มเหลว
with_env rails console

นอกจากนี้คุณยังสามารถเรียกใช้อินไลน์ (ตัวแปรสัมผัสกับเซสชันเทอร์มินัลปัจจุบันของคุณ): set -a && . ./.env && "$@" && echo "your comand here"
Giovanne Afonso

4

ฉันทำงานกับนักเทียบท่าเขียนและ.envไฟล์บน Mac และต้องการนำเข้า.envลงใน bash shell ของฉัน (สำหรับการทดสอบ) และคำตอบที่ "ดีที่สุด" ที่นี่คือการสะดุดกับตัวแปรต่อไปนี้:

.env

NODE_ARGS=--expose-gc --max_old_space_size=2048

สารละลาย

ดังนั้นฉันจึงใช้evalและห่อ env var defs ในเครื่องหมายคำพูดเดี่ยว

eval $(grep -v -e '^#' .env | xargs -I {} echo export \'{}\')

เวอร์ชั่น Bash

$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.


2

ฉันมีปัญหากับวิธีแก้ไขปัญหาที่แนะนำก่อนหน้านี้:

  • วิธีการแก้ปัญหา @ anubhava ทำให้การเขียนไฟล์การกำหนดค่าที่เป็นมิตรของ bash น่ารำคาญมากอย่างรวดเร็วและ - คุณอาจไม่ต้องการส่งออกการกำหนดค่าของคุณ
  • @Silas Paul solution แบ่งออกเมื่อคุณมีตัวแปรที่มีช่องว่างหรือตัวละครอื่น ๆ ที่ทำงานได้ดีในค่าที่ยกมา แต่$()ทำให้ยุ่งเหยิง

นี่คือวิธีแก้ปัญหาของฉันซึ่งยังคงเป็น IMO ที่แย่มากและไม่แก้ปัญหา "ส่งออกไปยังเด็กคนเดียว" โดย Silas (แต่คุณอาจเรียกใช้ใน sub-shell เพื่อ จำกัด ขอบเขต):

source .conf-file
export $(cut -d= -f1 < .conf-file)

2

ความต้องการของฉันคือ:

  • ไฟล์. env แบบง่าย ๆ ที่ไม่มีส่วนexportนำหน้า (สำหรับความเข้ากันได้กับ dotenv)
  • ค่าสนับสนุนในเครื่องหมายคำพูด: TEXT = "alpha bravo charlie"
  • สนับสนุนความคิดเห็นที่นำหน้าด้วย # และบรรทัดว่าง
  • เป็นสากลสำหรับทั้ง mac / BSD และ linux / GNU

เวอร์ชั่นเต็มใช้งานได้รวบรวมจากคำตอบข้างต้น:

  set -o allexport
  eval $(grep -v '^#' .env | sed 's/^/export /')
  set +o allexport

1
จุดของ "-o allexport" คืออะไรถ้าคุณเติมพวกเขาด้วย "ส่งออก" ต่อไป
il - ya

2

ก่อนอื่นให้สร้างไฟล์สภาพแวดล้อมที่จะมีคู่ค่าคีย์ทั้งหมดของสภาพแวดล้อมเช่นด้านล่างและตั้งชื่อสิ่งที่คุณต้องการในกรณีของฉันมัน env_var.env

MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"

จากนั้นสร้างสคริปต์ที่จะส่งออกตัวแปรสภาพแวดล้อมทั้งหมดสำหรับสภาพแวดล้อมแบบหลามเช่นด้านล่างและตั้งชื่อเช่น export_env.sh

#!/usr/bin/env bash

ENV_FILE="$1"
CMD=${@:2}

set -o allexport
source $ENV_FILE
set +o allexport

$CMD

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

การใช้:

./export_env.sh env_var.env python app.py

1

ฉันเจอชุดข้อความนี้เมื่อฉันพยายามนำ Docker กลับมาใช้ใหม่--env-fileในเปลือก รูปแบบของพวกเขานั้นไม่สามารถใช้งานร่วมกับทุบตีได้ แต่มันง่าย: name=valueไม่มีการอ้างถึงไม่มีการทดแทน พวกเขายังไม่สนใจบรรทัดว่างเปล่าและ#ความคิดเห็น

ฉันเข้ากันไม่ได้กับ posix แต่นี่เป็นอันที่ควรใช้กับเชลล์เหมือน bash (ทดสอบใน zsh บน OSX 10.12.5 และ bash บน Ubuntu 14.04):

while read -r l; do export "$(sed 's/=.*$//' <<<$l)"="$(sed -E 's/^[^=]+=//' <<<$l)"; done < <(grep -E -v '^\s*(#|$)' your-env-file)

มันจะไม่จัดการกับกรณีที่สามในตัวอย่างจากเอกสารที่เชื่อมโยงด้านบน:

  • bash: export: `123qwe=bar': not a valid identifier
  • bash: export: `org.spring.config=something': not a valid identifier
  • และจะไม่จัดการกับ passthrough syntax (a bare FOO)

1

ช่องว่างสีขาวในค่า

มีคำตอบที่ดีมากมายที่นี่ แต่ฉันพบว่าพวกเขาทั้งหมดขาดการสนับสนุนพื้นที่สีขาวตามตัวอักษร:

DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5

ฉันได้พบวิธีแก้ไข 2 วิธีที่ใช้งานได้กับค่าดังกล่าวพร้อมการสนับสนุนบรรทัดว่างเปล่าและความคิดเห็น

หนึ่งขึ้นอยู่กับ sed และ @ javier-buzzi คำตอบ :

source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x "&"/g' .env)

และอีกหนึ่งบรรทัดที่มีการอ่านในวงวนตาม @ john1024 คำตอบ

while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^\s|^$)" .env)

กุญแจสำคัญที่นี่คือการใช้declare -xและการวางสายในเครื่องหมายคำพูดคู่ ฉันไม่รู้ว่าทำไม แต่เมื่อคุณฟอร์แมตรหัสวนเป็นหลายบรรทัดมันจะไม่ทำงาน - ฉันไม่มีโปรแกรมเมอร์ทุบตีฉันแค่กลืนกันเหล่านี้มันยังคงมหัศจรรย์สำหรับฉัน :)


1
ฉันต้องแก้ไขsedโซลูชันเพื่อให้ทำงานได้ แต่ก่อนอื่นคำอธิบาย: -eสั้น--expressionซึ่งเพิ่งบอกsedว่าจะดำเนินการ -e /^$/dลบบรรทัดว่างออกจากผลลัพธ์ (ไม่ใช่ไฟล์) -e /^#/dลบความคิดเห็นของ bash (บรรทัดที่ขึ้นต้นด้วย #) จากเอาต์พุต 's/.*/declare -x "&"/g'แทนที่ (ทดแทน) declare -x "ENV_VAR="VALUE""ส่วนที่เหลืออีกเส้นที่มี อย่างน้อยสำหรับฉันมันไม่ได้ผล แต่ฉันต้องใช้source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x &/g' .env)เพื่อลบ"เสื้อคลุมพิเศษ
jcasner

ฉันไม่ได้ใช้ENV_VAR="lorem ipsum"ฉันมีENV_VAR=lorem ipsumโดยไม่มีเครื่องหมายคำพูดในไฟล์. env ตอนนี้ฉันไม่แน่ใจว่าทำไม แต่นี่อาจเป็นปัญหาในเครื่องมืออื่น ๆ ที่แยกไฟล์นี้ และแทนที่lorem ipsumฉันจะจบลงด้วย"lorem ipsum"มูลค่า - ด้วยคำพูด ขอบคุณสำหรับคำอธิบาย :)
Janusz Skonieczny

1
ถ้ามันเป็นทางเลือกของฉันฉันจะไม่ใช้ENV_VAR="lorem ipsum"อย่างใดอย่างหนึ่ง ในกรณีการใช้งานของฉันผู้ให้บริการโฮสต์ของฉันสร้างไฟล์นี้ตามตัวเลือกการกำหนดค่าบางอย่างที่ฉันได้ตั้งค่าและพวกเขาแทรกเครื่องหมายคำพูดคู่ ดังนั้นฉันถูกบังคับให้ต้องหลีกเลี่ยง ขอบคุณสำหรับความช่วยเหลือของคุณที่นี่ - ช่วยฉันประหยัดเวลาได้มากในการพยายามแก้ไขsedตัวเลือกที่ถูกต้องด้วยตัวเอง!
jcasner


1
t=$(mktemp) && export -p > "$t" && set -a && . ./.env && set +a && . "$t" && rm "$t" && unset t

มันทำงานอย่างไร

  1. สร้างไฟล์ชั่วคราว
  2. เขียนค่าตัวแปรสภาพแวดล้อมปัจจุบันทั้งหมดไปยังไฟล์ temp
  3. เปิดใช้งานการส่งออกตัวแปรที่ประกาศทั้งหมดในสคริปต์ต้นฉบับไปยังสภาพแวดล้อม
  4. อ่าน.envไฟล์ ตัวแปรทั้งหมดจะถูกส่งออกไปยังสภาพแวดล้อมปัจจุบัน
  5. ปิดใช้งานการส่งออกตัวแปรที่ประกาศไว้ทั้งหมดในสคริปต์ต้นฉบับไปยังสภาพแวดล้อม
  6. อ่านเนื้อหาของไฟล์ temp ทุกบรรทัดจะมีdeclare -x VAR="val"ที่จะส่งออกตัวแปรแต่ละตัวไปยังสภาพแวดล้อม
  7. ลบไฟล์ชั่วคราว
  8. ยกเลิกการตั้งชื่อตัวแปร temp ที่เก็บไว้

คุณสมบัติ

  • รักษาค่าของตัวแปรที่ตั้งค่าไว้แล้วในสภาพแวดล้อม
  • .env สามารถมีความคิดเห็น
  • .env สามารถมีบรรทัดว่างเปล่า
  • .envไม่ต้องใช้หัวกระดาษหรือท้ายกระดาษพิเศษเหมือนในคำตอบอื่น ๆ ( set -aและset +a)
  • .envไม่จำเป็นต้องมีexportสำหรับทุกค่า
  • หนึ่งในสายการบิน

0

หากคุณได้รับข้อผิดพลาดเนื่องจากหนึ่งในตัวแปรของคุณมีค่าที่มีช่องว่างสีขาวคุณสามารถลองรีเซ็ต bash's IFS(Internal Field Separator) \nเพื่อให้ bash ตีความcat .envผลลัพธ์เป็นรายการพารามิเตอร์สำหรับenvปฏิบัติการ

ตัวอย่าง:

IFS=$'\n'; env $(cat .env) rails c

ดูสิ่งนี้ด้วย:


0

ไฟล์. env ของฉันดูเหมือนว่า:

DATABASE_URI="postgres://sa:***@localhost:5432/my_db"
VARIABLE_1="SOME_VALUE"
VALIABLE_2="123456788"

เมื่อใช้วิธีของ@henkeค่าที่ส่งออกจะสิ้นสุดลงซึ่งมีเครื่องหมายคำพูด"

"postgres://sa:***@localhost:5432/my_db"
"SOME_VALUE"
"123456788"

แต่ฉันต้องการให้ค่าที่ส่งออกมีเพียง:

postgres://sa:***@localhost:5432/my_db
SOME_VALUE
123456788

หากต้องการแก้ไขฉันจะแก้ไขคำสั่งเพื่อลบเครื่องหมายคำพูด:

export $(grep -v '^#' dev.env | tr --delete '"' | xargs -d '\n')

0

สิ่งนี้เกี่ยวข้องกับช่องว่างบน RHS และข้าม 'แปลก' vars เช่นคำจำกัดความโมดูล bash (ด้วย '()' ในพวกเขา):

echo "# source this to set env vars" > $bld_dir/.env
env | while read line; do
    lhs="${line%%=*}"
    rhs="${line#*=}"
    if [[ "$lhs" =~ ^[0-9A-Za-z_]+$ ]]; then
        echo "export $lhs=\"$rhs\"" >> $bld_dir/.env
    fi
done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.