Environment Variables
Overview
The std::env module provides access to environment variables and process information. Query, set, and iterate over environment variables safely.
Code Example
#![allow(unused)]
fn main() {
use std::env;
// Iterate over environment variables
for (key, value) in env::vars().take(3) {
println!("{}: {}", key, value);
}
}
Explanation
env::vars(): Returns iterator over all environment variablestake(3): Limits to first 3 variables- Returns
(String, String)tuples of key-value pairs
Key Concepts
Reading Variables
#![allow(unused)]
fn main() {
use std::env;
// Get specific variable (returns Result)
match env::var("HOME") {
Ok(val) => println!("HOME: {}", val),
Err(e) => println!("Couldn't read HOME: {}", e),
}
// Get with default
let editor = env::var("EDITOR").unwrap_or("vim".to_string());
// Get as OsString (non-UTF8 safe)
let path = env::var_os("PATH");
}
Setting Variables
#![allow(unused)]
fn main() {
use std::env;
// Set for current process and children
env::set_var("MY_VAR", "my_value");
// Remove variable
env::remove_var("MY_VAR");
}
⚠️ Note: Changes only affect current process and child processes, not parent.
Process Information
#![allow(unused)]
fn main() {
// Current directory
let current_dir = env::current_dir()?;
// Change directory
env::set_current_dir("/tmp")?;
// Command line arguments
let args: Vec<String> = env::args().collect();
// Current executable path
let exe = env::current_exe()?;
}
Use Cases
- Configuration: Read config from environment
- CI/CD: Detect CI environment, read secrets
- System Info: Get user home, temp directory
- Path Resolution: Find executables in PATH
- Feature Flags: Enable/disable features via env vars
Best Practices
✅ Do:
- Use
var_os()for paths (handles non-UTF8) - Provide defaults with
.unwrap_or()or.unwrap_or_else() - Document required environment variables
- Validate variable values after reading
❌ Don’t:
- Assume variables exist (always handle
Result) - Store sensitive data in environment (can leak in logs)
- Modify environment in library code (side effects)
- Use
unwrap()without good reason
Common Environment Variables
Unix/Linux
HOME: User’s home directoryUSER: Current usernamePATH: Executable search pathSHELL: User’s shellLANG: Locale settings
Windows
USERPROFILE: User’s profile directoryUSERNAME: Current usernamePATH: Executable search pathTEMP/TMP: Temporary directory
Cross-Platform
#![allow(unused)]
fn main() {
use std::env;
fn get_home_dir() -> Option<PathBuf> {
env::var_os("HOME")
.or_else(|| env::var_os("USERPROFILE"))
.map(PathBuf::from)
}
}
Common Patterns
Configuration Loading
#![allow(unused)]
fn main() {
fn load_config() -> Config {
Config {
db_url: env::var("DATABASE_URL")
.expect("DATABASE_URL must be set"),
port: env::var("PORT")
.unwrap_or("8080".to_string())
.parse()
.expect("PORT must be a number"),
debug: env::var("DEBUG").is_ok(),
}
}
}
PATH Parsing
#![allow(unused)]
fn main() {
use std::env;
fn find_in_path(name: &str) -> Option<PathBuf> {
env::var_os("PATH")?
.split(|c| c == ':' || c == ';')
.map(PathBuf::from)
.find_map(|dir| {
let path = dir.join(name);
if path.exists() {
Some(path)
} else {
None
}
})
}
}
Temporary Directory
#![allow(unused)]
fn main() {
use std::env;
let temp_dir = env::temp_dir();
let temp_file = temp_dir.join("myapp_temp.txt");
}
Command Line Arguments
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
println!("Program: {}", args[0]);
if args.len() > 1 {
println!("First argument: {}", args[1]);
}
// Skip program name
for arg in env::args().skip(1) {
println!("Arg: {}", arg);
}
}
Related Features
- Path Operations - Working with filesystem paths
- Process Execution - Spawning child processes