Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม

หากคุณต้องการจัดการเว็บแอปอย่างมีประสิทธิภาพในการพัฒนาและใช้งานจริง คุณต้องเข้าใจตัวแปรสภาพแวดล้อม

นี่ไม่ใช่กรณีเสมอไป เมื่อไม่กี่ปีที่ผ่านมา แทบไม่มีใครกำหนดค่าแอป Rails ด้วยตัวแปรสภาพแวดล้อม แต่แล้ว Heroku ก็เกิดขึ้น

Heroku แนะนำนักพัฒนาให้รู้จักกับแนวทางแอป 12 ปัจจัย ในรายการแอป 12 ปัจจัย พวกเขาได้วางแนวทางปฏิบัติที่ดีที่สุดมากมายสำหรับการสร้างแอปที่ปรับใช้ได้ง่าย ส่วนเรื่องตัวแปรสภาพแวดล้อมมีอิทธิพลอย่างยิ่ง

แอพสโตร์สิบสองปัจจัยกำหนดค่าในตัวแปรสภาพแวดล้อม (มักจะย่อให้เหลือ env vars หรือ env) Env vars นั้นง่ายต่อการเปลี่ยนระหว่างการปรับใช้โดยไม่ต้องเปลี่ยนรหัสใดๆ ต่างจากไฟล์ปรับแต่ง มีโอกาสน้อยที่พวกเขาจะถูกตรวจสอบในที่เก็บโค้ดโดยไม่ได้ตั้งใจ และไม่เหมือนกับไฟล์กำหนดค่าที่กำหนดเองหรือกลไกการกำหนดค่าอื่นๆ เช่น Java System Properties ซึ่งเป็นมาตรฐานภาษาและ OS-agnostic

Rubyists จำนวนมากขึ้นใช้ตัวแปรสภาพแวดล้อมมากกว่าที่เคย แต่บ่อยครั้งก็เป็นเรื่องของการขนส่งสินค้า เรากำลังใช้สิ่งเหล่านี้โดยไม่เข้าใจจริงๆ ว่ามันทำงานอย่างไร

โพสต์นี้จะแสดงให้คุณเห็นว่าตัวแปรสภาพแวดล้อมทำงานอย่างไร และที่สำคัญกว่านั้นคือไม่ทำงาน นอกจากนี้ เราจะสำรวจวิธีทั่วไปบางส่วนในการจัดการตัวแปรสภาพแวดล้อมในแอป Rails ของคุณ เริ่มกันเลย!

หมายเหตุ:คุณสามารถอ่านเกี่ยวกับการรักษาความปลอดภัยตัวแปรสภาพแวดล้อมได้ที่นี่

ทุกกระบวนการมีชุดตัวแปรสภาพแวดล้อมของตัวเอง

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

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

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

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม ทุกกระบวนการมีสภาพแวดล้อมของตัวเอง

ตัวแปรสภาพแวดล้อมตายไปพร้อมกับกระบวนการของมัน

คุณเคยตั้งค่าตัวแปรสภาพแวดล้อม รีบูตแล้วพบว่ามันหายไปหรือไม่? เนื่องจากตัวแปรสภาพแวดล้อมเป็นของกระบวนการ ซึ่งหมายความว่าเมื่อใดก็ตามที่กระบวนการหยุดทำงาน ตัวแปรสภาพแวดล้อมของคุณจะหายไป

คุณสามารถดูสิ่งนี้ได้โดยการตั้งค่าตัวแปรสภาพแวดล้อมในเซสชัน IRB หนึ่งเซสชัน ปิด และพยายามเข้าถึงตัวแปรในเซสชัน irb ครั้งที่ 2

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม เมื่อกระบวนการปิดตัวลง ตัวแปรสภาพแวดล้อมจะหายไป

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

โปรเซสรับตัวแปรสภาพแวดล้อมจากพาเรนต์

ทุกกระบวนการมีพาเรนต์ นั่นเป็นเพราะว่าทุกโปรแกรมจะต้องเริ่มต้นจากโปรแกรมอื่น

หากคุณใช้ bash shell เพื่อเรียกใช้ vim พาเรนต์ของ vim ก็คือเชลล์ หากแอป Rails ของคุณใช้ imagemagick เพื่อระบุรูปภาพ แสดงว่าพาเรนต์ของ identify โปรแกรมจะเป็นแอป Rails ของคุณ

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม โปรเซสลูกรับค่า env vars จากพาเรนต์

ในตัวอย่างด้านล่าง ฉันกำลังตั้งค่าตัวแปรสภาพแวดล้อม $MARCO ในกระบวนการ IRB ของฉัน จากนั้นฉันก็ใช้ back-ticks เพื่อแยกและสะท้อนค่าของตัวแปรนั้น

เนื่องจาก IRB เป็นกระบวนการหลักของเชลล์ที่ฉันเพิ่งสร้างขึ้น มันจึงได้รับสำเนาของตัวแปรสภาพแวดล้อม $MARCO

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม ตัวแปรสภาพแวดล้อมที่ตั้งค่าใน Ruby นั้นสืบทอดมาจากกระบวนการย่อย

ผู้ปกครองสามารถปรับแต่งตัวแปรสภาพแวดล้อมที่ส่งไปยังบุตรหลานของตนได้

โดยค่าเริ่มต้น เด็กจะได้รับสำเนาของตัวแปรสภาพแวดล้อมทุกตัวที่พาเรนต์มี แต่ผู้ปกครองสามารถควบคุมสิ่งนี้ได้

จากบรรทัดคำสั่ง คุณสามารถใช้โปรแกรม env และใน bash มีไวยากรณ์พิเศษในการตั้งค่า env vars บนลูกโดยไม่ต้องตั้งค่าบนพาเรนต์

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม ใช้คำสั่ง env เพื่อตั้งค่าตัวแปรสภาพแวดล้อมสำหรับเด็กโดยไม่ต้องตั้งค่าบนพาเรนต์

หากคุณกำลังเชลล์ออกจากภายใน Ruby คุณยังสามารถจัดเตรียมตัวแปรสภาพแวดล้อมที่กำหนดเองให้กับกระบวนการลูกโดยไม่ทำให้แฮช ENV ของคุณหมดไป เพียงใช้ไวยากรณ์ต่อไปนี้กับ system วิธีการ:

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม วิธีส่งตัวแปรสภาพแวดล้อมที่กำหนดเองไปยังวิธีการระบบของ Ruby

บุตรหลานไม่สามารถตั้งค่าตัวแปรสภาพแวดล้อมของผู้ปกครองได้

เนื่องจากเด็กๆ จะได้รับเพียง สำเนา ของตัวแปรสภาพแวดล้อมของผู้ปกครอง การเปลี่ยนแปลงที่ทำโดยเด็กไม่มีผลกระทบต่อผู้ปกครอง

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม ตัวแปรสภาพแวดล้อม "ส่งผ่านโดยค่า" ไม่ใช่ "โดยการอ้างอิง"

ที่นี่ เราใช้ไวยากรณ์ back-tick เพื่อเชลล์ออกและพยายามตั้งค่าตัวแปรสภาพแวดล้อม แม้ว่าตัวแปรจะถูกตั้งค่าให้กับลูก ค่าใหม่จะไม่ขึ้นกับค่าระดับบนสุด

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม กระบวนการลูกไม่สามารถเปลี่ยนผู้ปกครองได้ env vars

การเปลี่ยนแปลงสภาพแวดล้อมจะไม่ซิงค์ระหว่างกระบวนการที่ทำงานอยู่

ในตัวอย่างด้านล่าง ฉันกำลังเรียกใช้ IRB สองชุดเคียงข้างกัน การเพิ่มตัวแปรในสภาพแวดล้อมของเซสชัน IRB หนึ่งไม่มีผลใดๆ กับเซสชัน IRB อื่น

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม การเพิ่มตัวแปรสภาพแวดล้อมให้กับกระบวนการหนึ่งจะไม่เปลี่ยนแปลงสำหรับกระบวนการอื่น

เชลล์ของคุณเป็นเพียง UI สำหรับระบบตัวแปรสภาพแวดล้อม

ระบบเองเป็นส่วนหนึ่งของเคอร์เนล OS นั่นหมายความว่าเปลือกไม่มีพลังวิเศษเหนือตัวแปรสภาพแวดล้อม ต้องปฏิบัติตามกฎเดียวกันกับทุกโปรแกรมที่คุณเรียกใช้

ตัวแปรสภาพแวดล้อมไม่เหมือนกับตัวแปรเชลล์

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

แต่ตัวแปรท้องถิ่นจะไม่ถูกคัดลอกไปยังลูกๆ

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม ตัวแปรสภาพแวดล้อมไม่เหมือนกับตัวแปรเชลล์

ลองมาดูตัวอย่างกัน ก่อนอื่นฉันตั้งค่าตัวแปรเชลล์ในเครื่องชื่อ MARCO เนื่องจากเป็นตัวแปรโลคัล จึงไม่คัดลอกไปยังโปรเซสลูกใดๆ ดังนั้นเมื่อฉันพยายามพิมพ์ผ่าน Ruby มันใช้งานไม่ได้

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

คู่มือ Rubyists เกี่ยวกับตัวแปรสภาพแวดล้อม โปรเซสลูกไม่มีตัวแปรในเครื่อง การส่งออกแปลงตัวแปรท้องถิ่นเป็นตัวแปรสภาพแวดล้อม

การจัดการตัวแปรสภาพแวดล้อมในทางปฏิบัติ

ทั้งหมดนี้ทำงานอย่างไรในโลกแห่งความเป็นจริง? มาทำตัวอย่างกัน:

สมมติว่าคุณมีแอป 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 ของผู้ใช้เพื่อเก็บค่าเฉพาะแอปพลิเคชันได้