I have a shell script which I want to run at login as well as logout.
It's something like this
#!/bin/bash
# Define the log file path
LOG_FILE="/Users/kamabokogonpachiro/Desktop/logfile.log"
# Function to log login
log_login() {
echo "$(date) - User $1 logged in" >> "$LOG_FILE"
}
# Function to log logout
log_logout() {
echo "$(date) - User $1 logged out" >> "$LOG_FILE"
}
# Check if the script is called with a username argument
if [ "$1" ]; then
# If the script is called with "logout" as the first argument, log the logout
if [ "$1" = "logout" ]; then
log_logout "$2"
else
# Otherwise, log the login
log_login "$1"
fi
fi
The login script is saved at ~/Library/LaunchAgents/com.user.login.plist and the contents are
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.login.sh</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/kamabokogonpachiro/Desktop/logfile.sh</string>
<string>login</string>
<string>$(whoami)</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>WorkingDirectory</key>
<string>/Users/kamabokogonpachiro/Desktop</string>
</dict>
</plist>
Similarly the logout script is located at ~/Library/LogoutAgents/com.user.logout.plist and the contents are
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.logout</string>
<key>ProgramArguments</key>
<array>
<string>/Users/kamabokogonpachiro/Desktop/logfile.sh</string>
<string>logout</string>
<string>username</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
I did launchctl load ... as well.
Still, they are not working the shell script is marked as executable as well. I don't know what am I missing. Is my approach incorrect? Are there any better ways? I tried with last but the BSD one is different from the Linux (GNU) one and not that versatile.
I don't think you can use shell facilities like a command substitution
$(whoami)in the.plistfile; it will simply be passed in as a literal string, as if you had written single quotes around it in the shell.Just refactor your script to run
whoamiif the first argument islogin; or perhaps simply use$USERwhich will already be set by the system.You also seem to have forgotten to include the
Programkey in your.plistfiles. I don't know if Bash cares, but I'd add it just in case.Tangentially, it's weird to do these things in the user's
Desktopdirectory. Probably create a hidden file in the user's home directory instead; the user can create a symlink to it on their desktop if they like. I have similarly changed the location of the binary to be in yourbinbelow.See also https://apple.stackexchange.com/questions/110644/getting-launchd-to-read-program-arguments-correctly
Also, don't use upper case for your private variables.