Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 12, 2023 12:07 pm GMT

Where is my PATH, launchD?

Originally published here.

While working on the macOS support for agent-aws-stack, I ran into a small issue with launchD. My scenario was: a Go binary executed as a launchD daemon. That daemon, upon termination, executes (in a non-login shell) a bash script:

token=$(curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 60" --fail --silent --show-error --location "http://169.254.169.254/latest/api/token")instance_id=$(curl -H "X-aws-ec2-metadata-token: $token" --fail --silent --show-error --location "http://169.254.169.254/latest/meta-data/instance-id")region=$(curl -H "X-aws-ec2-metadata-token: $token" --fail --silent --show-error --location "http://169.254.169.254/latest/meta-data/placement/region")aws autoscaling terminate-instance-in-auto-scaling-group \    --region "$region" \    --instance-id "$instance_id" \    --no-should-decrement-desired-capacity

All the script does is terminate the EC2 instance and remove it from the auto-scaling group.

In a Linux machine, as a systemD unit, the script executes successfully. However, in macOS, as a launchD daemon, it doesn't. The script doesn't find the AWS CLI, exits with exit code 127, and displays that error message we all know and love:

aws: command not found

The AWS CLI is located at /usr/local/bin/aws, but our PATH when the script is executed is PATH=/usr/bin:/bin:/usr/sbin:/sbin. For some reason, launchD is not including /usr/local/bin in the PATH it exposes to its daemons, as systemD does.

The reason it works on systemD

You can see the environment systemD exposes to its system and user units using the show-environment command:

$ systemctl show-environmentLANG=C.UTF-8PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin$ systemctl --user show-environmentHOME=/home/ubuntuLANG=C.UTF-8LOGNAME=ubuntuPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/binSHELL=/bin/bashSYSTEMD_EXEC_PID=1260USER=ubuntuXDG_RUNTIME_DIR=/run/user/1000XDG_DATA_DIRS=/usr/local/share/:/usr/share/:/var/lib/snapd/desktopDBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

Where does that environment come from? From environment generators. SystemD comes with a default one which loads the environment from some special places.

What about launchD?

I was expecting launchD to have at least some environment setup for its daemons, but it doesn't. At least, not a default one, like systemD. There are a few different ways to configure it, though.

1. In the .plist daemon configuration

In our launchD daemon configuration (located at /Library/LaunchDaemons), we can explicitly add the PATH variable we want:

<!-- rest of plist --><key>EnvironmentVariables</key><dict>  <key>PATH</key>  <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string></dict><!-- rest of plist -->

2. Using launchctl setenv

From launchctl's man page:

setenv key value    Specify an environment variable to be set on all future processes launched by launchd in the caller's context.

This would require restarting our daemon.

3. Using launchctl config

From launchctl's man page:

config system | user parameter value      Sets persistent configuration information for launchd(8) domains. Only the system domain and user domains may be configured. The location of the persistent storage is an implementation detail, and changes to that storage should only be made through this subcommand. A reboot is required for changes made through this subcommand to take effect.      Supported configuration parameters are:      umask    Sets the umask(2) for services within the target domain to the value specified by value. Note that this value is parsed by               strtoul(3) as an octal-encoded number, so there is no need to prefix it with a leading '0'.      path     Sets the PATH environment variable for all services within the target domain to the string value. The string value should               conform to the format outlined for the PATH environment variable in environ(7). Note that if a service specifies its own PATH,               the service-specific environment variable will take precedence.               NOTE: This facility cannot be used to set general environment variables for all services within the domain. It is intentionally scoped to the PATH environment variable and nothing else for security reasons.

This would require a reboot, though.

Note: previously (on macOS versions < 10.10), you could use /etc/launchd.conf, but that doesnt work on newer versions.

Conclusion

As the only thing I needed was to use the AWS CLI, I temporarily added the /usr/local/bin to the PATH in the script itself and called it a day.

In hindsight, I could've just done that in the first place and seen if the script would work. But it's nice to understand what is going on before choosing a simpler fix.

Other resources


Original Link: https://dev.to/lucaspin/where-is-my-path-launchd-bi0

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To