When your system boots, init.d scripts execute with a minimal environment. Unlike your interactive shell session, these scripts don't inherit your custom PATH settings. This explains why commands in /usr/local/bin
aren't found during startup.
Many modern development tools (like Ruby's bundler, npm global packages, or Python utilities) install into /usr/local/bin
. During normal operation, your shell profile adds this to PATH, but the init system runs before these profiles load.
# Check your normal PATH vs. init PATH
echo $PATH # Your interactive shell
cat /proc/1/environ | tr '\\0' '\\n' | grep PATH # Init system PATH
1. Absolute Paths in Script
The most robust approach is using full paths to commands:
#!/bin/sh
case "$1" in
start)
echo "starting"
cd /path && /usr/local/bin/bundle exec /usr/local/bin/unicorn \
-c /path/config/unicorn.rb -D -E production
;;
stop)
echo "Stopping Unicorn Instances"
/bin/kill cat /tmp/unicorn.pid
;;
restart)
echo "sending USR2 to all unicorns"
/bin/kill -s USR2 cat /tmp/unicorn.pid
;;
esac
exit 0
2. Set PATH in Script Header
Alternatively, explicitly set PATH at the beginning of your init script:
#!/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
# Rest of script remains unchanged
3. Environment File Method (Debian/Ubuntu)
Create an environment file for your service:
# /etc/default/unicorn_boot
PATH="/usr/local/bin:/usr/bin:/bin"
export PATH
Then source it in your init script:
#!/bin/sh
[ -f /etc/default/unicorn_boot ] && . /etc/default/unicorn_boot
Verify your script works with the minimal boot environment:
# Simulate init environment
env -i PATH=/usr/bin:/bin /etc/init.d/unicorn_boot.sh start
If using newer systems with systemd, create a service unit file with proper environment settings:
[Unit]
Description=Unicorn Application Server
[Service]
Environment=PATH=/usr/local/bin:/usr/bin:/bin
WorkingDirectory=/path/to/app
ExecStart=/usr/local/bin/bundle exec unicorn -c config/unicorn.rb -E production
PIDFile=/tmp/unicorn.pid
Restart=always
[Install]
WantedBy=multi-user.target
When dealing with system startup scripts on Ubuntu, you might encounter situations where commands that work perfectly when executed manually fail during boot. The core issue often stems from environment variable differences, particularly the PATH variable.
# Example error you might see in logs:
/etc/rc2.d/S20unicorn_boot.sh: bundle: not found
During system initialization, the environment is much more restricted than your regular user shell. Many standard paths aren't included in the PATH variable by default, including /usr/local/bin where tools like Ruby's bundle are often installed.
Here are several approaches to ensure your scripts have the correct PATH during boot:
1. Explicitly Set PATH in Your Script
#!/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
case "$1" in
start)
echo "starting"
cd /path && bundle exec unicorn -c /path/config/unicorn.rb -D -E production
;;
stop)
echo "Stopping Unicorn Instances"
kill cat /tmp/unicorn.pid
;;
restart)
echo "sending USR2 to all unicorns"
kill -s USR2 cat /tmp/unicorn.pid
;;
esac
exit 0
2. Source the Default Environment
#!/bin/sh
. /etc/environment
# Rest of your script remains the same
3. Use Absolute Paths for Critical Commands
#!/bin/sh
case "$1" in
start)
echo "starting"
cd /path && /usr/local/bin/bundle exec /usr/local/bin/unicorn -c /path/config/unicorn.rb -D -E production
;;
# ... rest of the script
- Always test scripts by running them with a minimal environment:
env -i /path/to/script
- Consider using full paths for all commands in production scripts
- Log environment variables during boot for debugging:
env > /var/log/script-env.log
For modern Ubuntu systems (15.04+), consider migrating to systemd service units which provide better environment handling:
[Unit]
Description=Unicorn Application Server
After=network.target
[Service]
Type=forking
User=deploy
WorkingDirectory=/path/to/app
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
ExecStart=/usr/local/bin/bundle exec unicorn -c /path/config/unicorn.rb -D -E production
PIDFile=/tmp/unicorn.pid
Restart=always
[Install]
WantedBy=multi-user.target