หากคุณต้องการจัดการเว็บแอปอย่างมีประสิทธิภาพในการพัฒนาและใช้งานจริง คุณต้องเข้าใจตัวแปรสภาพแวดล้อม
นี่ไม่ใช่กรณีเสมอไป เมื่อไม่กี่ปีที่ผ่านมา แทบไม่มีใครกำหนดค่าแอป Rails ด้วยตัวแปรสภาพแวดล้อม แต่แล้ว Heroku ก็เกิดขึ้น
Heroku แนะนำนักพัฒนาให้รู้จักกับแนวทางแอป 12 ปัจจัย ในรายการแอป 12 ปัจจัย พวกเขาได้วางแนวทางปฏิบัติที่ดีที่สุดมากมายสำหรับการสร้างแอปที่ปรับใช้ได้ง่าย ส่วนเรื่องตัวแปรสภาพแวดล้อมมีอิทธิพลอย่างยิ่ง
แอพสโตร์สิบสองปัจจัยกำหนดค่าในตัวแปรสภาพแวดล้อม (มักจะย่อให้เหลือ env vars หรือ env) Env vars นั้นง่ายต่อการเปลี่ยนระหว่างการปรับใช้โดยไม่ต้องเปลี่ยนรหัสใดๆ ต่างจากไฟล์ปรับแต่ง มีโอกาสน้อยที่พวกเขาจะถูกตรวจสอบในที่เก็บโค้ดโดยไม่ได้ตั้งใจ และไม่เหมือนกับไฟล์กำหนดค่าที่กำหนดเองหรือกลไกการกำหนดค่าอื่นๆ เช่น Java System Properties ซึ่งเป็นมาตรฐานภาษาและ OS-agnostic
Rubyists จำนวนมากขึ้นใช้ตัวแปรสภาพแวดล้อมมากกว่าที่เคย แต่บ่อยครั้งก็เป็นเรื่องของการขนส่งสินค้า เรากำลังใช้สิ่งเหล่านี้โดยไม่เข้าใจจริงๆ ว่ามันทำงานอย่างไร
โพสต์นี้จะแสดงให้คุณเห็นว่าตัวแปรสภาพแวดล้อมทำงานอย่างไร และที่สำคัญกว่านั้นคือไม่ทำงาน นอกจากนี้ เราจะสำรวจวิธีทั่วไปบางส่วนในการจัดการตัวแปรสภาพแวดล้อมในแอป Rails ของคุณ เริ่มกันเลย!
หมายเหตุ:คุณสามารถอ่านเกี่ยวกับการรักษาความปลอดภัยตัวแปรสภาพแวดล้อมได้ที่นี่
ทุกกระบวนการมีชุดตัวแปรสภาพแวดล้อมของตัวเอง
ทุกโปรแกรมที่คุณเรียกใช้บนเซิร์ฟเวอร์ของคุณมีอย่างน้อยหนึ่งกระบวนการ กระบวนการนั้นได้รับชุดของตัวแปรสภาพแวดล้อมของตัวเอง เมื่อมีแล้ว สิ่งใดนอกกระบวนการนั้นไม่สามารถเปลี่ยนแปลงได้
ข้อผิดพลาดที่เข้าใจได้ซึ่งผู้เริ่มต้นทำคือการคิดว่าตัวแปรสภาพแวดล้อมเป็นแบบทั่วทั้งเซิร์ฟเวอร์ บริการต่างๆ เช่น Heroku ทำให้ดูเหมือนว่าการตั้งค่าตัวแปรสภาพแวดล้อมจะเทียบเท่ากับการแก้ไขไฟล์กำหนดค่าบนดิสก์ แต่ตัวแปรสภาพแวดล้อมไม่เหมือนไฟล์ปรับแต่ง
ทุกโปรแกรมที่คุณเรียกใช้บนเซิร์ฟเวอร์จะได้รับชุดตัวแปรสภาพแวดล้อมของตัวเองทันทีที่คุณเปิดเครื่อง
ทุกกระบวนการมีสภาพแวดล้อมของตัวเอง
ตัวแปรสภาพแวดล้อมตายไปพร้อมกับกระบวนการของมัน
คุณเคยตั้งค่าตัวแปรสภาพแวดล้อม รีบูตแล้วพบว่ามันหายไปหรือไม่? เนื่องจากตัวแปรสภาพแวดล้อมเป็นของกระบวนการ ซึ่งหมายความว่าเมื่อใดก็ตามที่กระบวนการหยุดทำงาน ตัวแปรสภาพแวดล้อมของคุณจะหายไป
คุณสามารถดูสิ่งนี้ได้โดยการตั้งค่าตัวแปรสภาพแวดล้อมในเซสชัน IRB หนึ่งเซสชัน ปิด และพยายามเข้าถึงตัวแปรในเซสชัน irb ครั้งที่ 2
เมื่อกระบวนการปิดตัวลง ตัวแปรสภาพแวดล้อมจะหายไป
นี่เป็นหลักการเดียวกันที่ทำให้คุณสูญเสียตัวแปรสภาพแวดล้อมเมื่อเซิร์ฟเวอร์ของคุณรีบูต หรือเมื่อคุณออกจากเชลล์ของคุณ หากต้องการให้คงอยู่ในเซสชันต่างๆ คุณต้องเก็บไว้ในไฟล์การกำหนดค่าบางประเภท เช่น .bashrc
.
โปรเซสรับตัวแปรสภาพแวดล้อมจากพาเรนต์
ทุกกระบวนการมีพาเรนต์ นั่นเป็นเพราะว่าทุกโปรแกรมจะต้องเริ่มต้นจากโปรแกรมอื่น
หากคุณใช้ bash shell เพื่อเรียกใช้ vim พาเรนต์ของ vim ก็คือเชลล์ หากแอป Rails ของคุณใช้ imagemagick เพื่อระบุรูปภาพ แสดงว่าพาเรนต์ของ identify
โปรแกรมจะเป็นแอป Rails ของคุณ
โปรเซสลูกรับค่า env vars จากพาเรนต์
ในตัวอย่างด้านล่าง ฉันกำลังตั้งค่าตัวแปรสภาพแวดล้อม $MARCO ในกระบวนการ IRB ของฉัน จากนั้นฉันก็ใช้ back-ticks เพื่อแยกและสะท้อนค่าของตัวแปรนั้น
เนื่องจาก IRB เป็นกระบวนการหลักของเชลล์ที่ฉันเพิ่งสร้างขึ้น มันจึงได้รับสำเนาของตัวแปรสภาพแวดล้อม $MARCO
ตัวแปรสภาพแวดล้อมที่ตั้งค่าใน Ruby นั้นสืบทอดมาจากกระบวนการย่อย
ผู้ปกครองสามารถปรับแต่งตัวแปรสภาพแวดล้อมที่ส่งไปยังบุตรหลานของตนได้
โดยค่าเริ่มต้น เด็กจะได้รับสำเนาของตัวแปรสภาพแวดล้อมทุกตัวที่พาเรนต์มี แต่ผู้ปกครองสามารถควบคุมสิ่งนี้ได้
จากบรรทัดคำสั่ง คุณสามารถใช้โปรแกรม env และใน bash มีไวยากรณ์พิเศษในการตั้งค่า env vars บนลูกโดยไม่ต้องตั้งค่าบนพาเรนต์
ใช้คำสั่ง env เพื่อตั้งค่าตัวแปรสภาพแวดล้อมสำหรับเด็กโดยไม่ต้องตั้งค่าบนพาเรนต์
หากคุณกำลังเชลล์ออกจากภายใน Ruby คุณยังสามารถจัดเตรียมตัวแปรสภาพแวดล้อมที่กำหนดเองให้กับกระบวนการลูกโดยไม่ทำให้แฮช ENV ของคุณหมดไป เพียงใช้ไวยากรณ์ต่อไปนี้กับ system
วิธีการ:
วิธีส่งตัวแปรสภาพแวดล้อมที่กำหนดเองไปยังวิธีการระบบของ Ruby
บุตรหลานไม่สามารถตั้งค่าตัวแปรสภาพแวดล้อมของผู้ปกครองได้
เนื่องจากเด็กๆ จะได้รับเพียง สำเนา ของตัวแปรสภาพแวดล้อมของผู้ปกครอง การเปลี่ยนแปลงที่ทำโดยเด็กไม่มีผลกระทบต่อผู้ปกครอง
ตัวแปรสภาพแวดล้อม "ส่งผ่านโดยค่า" ไม่ใช่ "โดยการอ้างอิง"
ที่นี่ เราใช้ไวยากรณ์ back-tick เพื่อเชลล์ออกและพยายามตั้งค่าตัวแปรสภาพแวดล้อม แม้ว่าตัวแปรจะถูกตั้งค่าให้กับลูก ค่าใหม่จะไม่ขึ้นกับค่าระดับบนสุด
กระบวนการลูกไม่สามารถเปลี่ยนผู้ปกครองได้ env vars
การเปลี่ยนแปลงสภาพแวดล้อมจะไม่ซิงค์ระหว่างกระบวนการที่ทำงานอยู่
ในตัวอย่างด้านล่าง ฉันกำลังเรียกใช้ IRB สองชุดเคียงข้างกัน การเพิ่มตัวแปรในสภาพแวดล้อมของเซสชัน IRB หนึ่งไม่มีผลใดๆ กับเซสชัน IRB อื่น
การเพิ่มตัวแปรสภาพแวดล้อมให้กับกระบวนการหนึ่งจะไม่เปลี่ยนแปลงสำหรับกระบวนการอื่น
เชลล์ของคุณเป็นเพียง UI สำหรับระบบตัวแปรสภาพแวดล้อม
ระบบเองเป็นส่วนหนึ่งของเคอร์เนล OS นั่นหมายความว่าเปลือกไม่มีพลังวิเศษเหนือตัวแปรสภาพแวดล้อม ต้องปฏิบัติตามกฎเดียวกันกับทุกโปรแกรมที่คุณเรียกใช้
ตัวแปรสภาพแวดล้อมไม่เหมือนกับตัวแปรเชลล์
ความเข้าใจผิดที่ใหญ่ที่สุดประการหนึ่งเกิดขึ้นเนื่องจากเชลล์จัดเตรียมระบบตัวแปรเชลล์ "ในเครื่อง" ของตัวเอง ไวยากรณ์สำหรับการใช้ตัวแปรโลคัลมักจะเหมือนกับตัวแปรสภาพแวดล้อม และผู้เริ่มต้นมักจะสับสนทั้งสอง
แต่ตัวแปรท้องถิ่นจะไม่ถูกคัดลอกไปยังลูกๆ
ตัวแปรสภาพแวดล้อมไม่เหมือนกับตัวแปรเชลล์
ลองมาดูตัวอย่างกัน ก่อนอื่นฉันตั้งค่าตัวแปรเชลล์ในเครื่องชื่อ MARCO เนื่องจากเป็นตัวแปรโลคัล จึงไม่คัดลอกไปยังโปรเซสลูกใดๆ ดังนั้นเมื่อฉันพยายามพิมพ์ผ่าน Ruby มันใช้งานไม่ได้
ต่อไป ฉันใช้คำสั่ง export เพื่อแปลงตัวแปรโลคัลเป็นตัวแปรสภาพแวดล้อม ตอนนี้มันถูกคัดลอกไปยังทุกกระบวนการใหม่ที่สร้างเชลล์นี้ ตอนนี้ตัวแปรสภาพแวดล้อมพร้อมใช้งานสำหรับ Ruby แล้ว
โปรเซสลูกไม่มีตัวแปรในเครื่อง การส่งออกแปลงตัวแปรท้องถิ่นเป็นตัวแปรสภาพแวดล้อม
การจัดการตัวแปรสภาพแวดล้อมในทางปฏิบัติ
ทั้งหมดนี้ทำงานอย่างไรในโลกแห่งความเป็นจริง? มาทำตัวอย่างกัน:
สมมติว่าคุณมีแอป Rails สองแอปที่ทำงานบนคอมพิวเตอร์เครื่องเดียว คุณกำลังใช้ Honeybadger เพื่อตรวจสอบแอปเหล่านี้เพื่อหาข้อยกเว้น แต่คุณประสบปัญหา
คุณต้องการจัดเก็บคีย์ Honeybadger API ของคุณในตัวแปรสภาพแวดล้อม $HONEYBADGER_API_KEY แต่แอปทั้งสองของคุณมีคีย์ API สองคีย์แยกกัน
ตัวแปรสภาพแวดล้อมหนึ่งตัวจะมีค่าต่างกันสองค่าได้อย่างไร
ตอนนี้ฉันหวังว่าคุณจะรู้คำตอบ เนื่องจาก env vars เป็นแบบต่อกระบวนการ และแอป Rails สองอันของฉันทำงานในกระบวนการที่แตกต่างกัน ไม่มีเหตุผลใดที่แต่ละแอปจะมีมูลค่า $HONEYBADGER_API_KEY เป็นของตัวเอง
ตอนนี้คำถามเดียวคือวิธีการตั้งค่า โชคดีที่มีอัญมณีอยู่สองสามอย่างที่ทำให้สิ่งนี้ง่ายจริงๆ
ฟิกาโร
เมื่อคุณติดตั้ง Figaro gem ในแอป Rails ค่าใดๆ ที่คุณป้อนลงใน config/application.yml จะถูกโหลดลงในแฮช ruby ENV เมื่อเริ่มต้น
คุณเพียงแค่ติดตั้งอัญมณี:
# Gemfile
gem "figaro"
และเริ่มเพิ่มรายการใน application.yml เป็นสิ่งสำคัญมากที่คุณจะต้องเพิ่มไฟล์นี้ใน .gitignore ของคุณ เพื่อไม่ให้คุณเปิดเผยความลับของคุณโดยไม่ได้ตั้งใจ
# config/application.yml
HONEYBADGER_API_KEY: 12345
โดเท็นฟ
dotenv gem นั้นคล้ายกับ Figaro มาก ยกเว้นว่าจะโหลดตัวแปรสภาพแวดล้อมจาก .env และไม่ได้ใช้ YAML
เพียงติดตั้งอัญมณี:
# Gemfile
gem 'dotenv-rails'
และเพิ่มค่าการกำหนดค่าของคุณลงใน .env - และตรวจสอบให้แน่ใจว่าคุณ git ละเว้นไฟล์นั้น เพื่อที่คุณจะได้ไม่เผยแพร่ไปยัง github โดยไม่ได้ตั้งใจ
HONEYBADGER_API_KEY=12345
จากนั้นคุณสามารถเข้าถึงค่าในแฮช Ruby ENV ของคุณ
ENV["HONEYBADGER_API_KEY"]
คุณยังสามารถเรียกใช้คำสั่งในเชลล์ด้วยชุด env vars ที่กำหนดไว้ล่วงหน้าได้ดังนี้:
dotenv ./my_script.sh
ความลับ.yml?
เสียใจ. Secrets.yml - แม้ว่าจะเจ๋ง - ไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อม ดังนั้นจึงใช้แทนอัญมณีอย่าง Figaro และ dotenv ไม่ได้
Linux เก่าแบบธรรมดา
นอกจากนี้ยังสามารถรักษาชุดตัวแปรสภาพแวดล้อมที่ไม่ซ้ำกันต่อแอพโดยใช้คำสั่งพื้นฐาน linux วิธีหนึ่งคือการให้แต่ละแอปทำงานบนเซิร์ฟเวอร์ของคุณเป็นของผู้ใช้ที่แตกต่างกัน จากนั้นคุณสามารถใช้ .bashrc ของผู้ใช้เพื่อเก็บค่าเฉพาะแอปพลิเคชันได้