When working with the service
command in Linux, many administrators encounter unexpected behavior regarding environment variables. The manual page explicitly states:
service runs a System V init script in as predictable environment as possible,
removing most environment variables and with current working directory set to /.
This behavior is intentional to create a clean, predictable environment for service execution. However, it can cause issues when your service relies on specific environment variables.
The typical approaches that don't work include:
- Setting variables in
/etc/profile.d/
or~/.bashrc
- Exporting variables in the shell before running
service
- Using
source
commands in the init script
Method 1: Using /etc/default Files
Many services support reading configuration from /etc/default/[servicename]
:
# /etc/default/myservice
export MY_VAR="/path/to/required/directory"
Then modify your init script to source this file:
# /etc/init.d/myservice
[ -f /etc/default/myservice ] && . /etc/default/myservice
Method 2: Systemd EnvironmentFile Directive
For systems using systemd (most modern distributions):
# /etc/systemd/system/myservice.service
[Service]
EnvironmentFile=/etc/sysconfig/myservice
ExecStart=/usr/bin/myservice
Create the environment file:
# /etc/sysconfig/myservice
MY_VAR="/path/to/required/directory"
Method 3: Direct Modification of Init Script
For legacy systems where other methods aren't feasible:
# /etc/init.d/myservice
# Add near the top of the file
export MY_VAR="/path/to/required/directory"
- Security: Environment variables in /etc/default files should have restricted permissions (640 root:root)
- Portability: The /etc/default method works across most Linux distributions
- Maintainability: Separate configuration from init scripts for easier updates
To verify your environment is properly configured:
# Add to your init script before the service starts
env > /tmp/service-env.log
This will create a log file showing exactly what environment the service sees during startup.
When working with System V init scripts on Linux, many developers encounter this frustrating scenario: environment variables set in /etc/profile.d/
or shell configurations mysteriously disappear when starting services via the service
command. This behavior is actually documented in the man pages - the service
command intentionally strips most environment variables to create a clean, predictable execution environment.
# Example of the issue
$ export MY_APP_PATH=/opt/myapp
$ service myapp start # MY_APP_PATH won't be available
The service
wrapper does several things that affect environment variables:
- Changes working directory to
/
- Removes most inherited environment variables
- Only preserves a minimal set (PATH, TERM, LANG, etc.)
- Runs scripts with
env -i
for clean environment
1. Modify the init script directly
The most straightforward approach is to edit the init script to include required variables:
# /etc/init.d/myapp
#!/bin/sh
# Add variables at the top
export MY_APP_PATH=/opt/myapp
export CONFIG_FILE=/etc/myapp.conf
# Rest of init script...
2. Use systemd service files (modern systems)
For systems using systemd, create or modify the service unit file:
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
[Service]
Environment="MY_APP_PATH=/opt/myapp"
Environment="CONFIG_FILE=/etc/myapp.conf"
ExecStart=/usr/bin/myapp
Restart=on-failure
[Install]
WantedBy=multi-user.target
3. Create a wrapper script
For systems where you can't modify the init script:
# /usr/local/bin/myapp-wrapper
#!/bin/bash
export MY_APP_PATH=/opt/myapp
export CONFIG_FILE=/etc/myapp.conf
exec /etc/init.d/myapp-original "$@"
# Then update service to point to the wrapper
When choosing a solution, consider:
- Security implications of environment variables
- Maintainability across updates
- Portability between systems
- Need for variable substitution (e.g., using $HOME)
For sensitive values, consider using configuration files instead of environment variables, or use tools like envdir
for more controlled variable management.