AWS Thinkbox Discussion Forums

Disable worker at logon

Summary
On windows, we run a logon/off script callind deadlinecommand to disable workers when a user logs in. Works great.
Cert error on osx when running as Launch Agent, but works fine as any user in terminal.

Prefer this to killing service so we can differentiate between a offline/shutdown and logged in state.

Windows commands
logon, only SlaveEnabled True for logout

deadlinecommand RemoteControl %COMPUTERNAME% ForceStopSlave
deadlinecommand SetSlaveSetting %COMPUTERNAME% SlaveEnabled False
deadlinecommand RemoteControl %COMPUTERNAME% LaunchSlave

macos setup
Replicating on osx with a LaunchAgent that calls bash script

<?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>EnableGlobbing</key>
	<true/>
	<key>EnableTransactions</key>
	<false/>
	<key>Label</key>
	<string>com.svad.svad_logout</string>
	<key>LimitLoadToSessionType</key>
	<string>Aqua</string>
	<key>ProgramArguments</key>
	<array>
		<string>/bin/sh</string>
		<string>/usr/local/bin/svad/svad_logout.sh</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>StandardErrorPath</key>
	<string>/Users/Shared/svad_logout_stderr.log</string>
	<key>StandardOutPath</key>
	<string>/Users/Shared/svad_logout_stdout.log</string>
</dict>
</plist>
#!/bin/sh

# Get the computer name using scutil and export it to HOSTNAME
export HOSTNAME=$(scutil --get ComputerName)

# Define the log file path
log_file="/Users/Shared/svad_logout.sh.log"
# Get the current date and time
current_time=$(date +"%Y-%m-%d %H:%M:%S")

# Write timestamp to log
echo "Logging in: $current_time" >> "$log_file"

# Execute the deadline command with the computer name
/Applications/Thinkbox/Deadline10/Resources/deadlinecommand RemoteControl $HOSTNAME ForceStopSlave
/Applications/Thinkbox/Deadline10/Resources/deadlinecommand SetSlaveSetting $HOSTNAME SlaveEnabled False
/Applications/Thinkbox/Deadline10/Resources/deadlinecommand RemoteControl $HOSTNAME LaunchSlave

onLogout() {

    # Get the current date and time
    current_time=$(date +"%Y-%m-%d %H:%M:%S")

    # Write timestamp to log
    echo "Logging out: $current_time" >> "$log_file"

    # Execute the deadline command with the computer name
    /Applications/Thinkbox/Deadline10/Resources/deadlinecommand SetSlaveSetting $HOSTNAME SlaveEnabled True

    exit
}

trap 'onLogout' SIGINT SIGHUP SIGTERM
while true; do
    sleep 86400 &
    wait $!
done

The RemoteControl commands work fine, but the SetSlaveSetting throws an error.

Sent remote command 'ForceStopSlave' to: [SVAD-UTL-13].
Set SlaveEnabled to False.
SVAD-UTL-13: Sent "LaunchSlave" command. Result: "Connection Accepted."
Sent remote command 'LaunchSlave' to: [SVAD-UTL-13].
Error: Error encountered when loading the configured Client Certificate (/Applications/Thinkbox/Deadline10RemoteClient.pfx). It is likely either an invalid x.509 certificate, or the wrong passphrase was provided.

Full Error:
One or more parameters passed to a function were not valid. (Deadline.Configuration.DeadlineConfigException)

the SetSlaveSetting works fine logged in as any user from terminal. What would be causing the failure when running as an agent?

Thanks!
Zach

Digging more, it appears to work on login, but not logout probably due to keychain access.
My guess is the cert password is stored in some keychain and it looses access during logout.

Neither command works during logout.

  • I attempted to use RunCommandForRepository but struck out.

  • Is there an easy way to remove the password requirement from the cert? Don’t really need it, just followed recommendations during install. (cert is on each machine, wasn’t sure of best practices for distributing it)

The stderr points to keychain related issues.

CSSM_ModuleLoad(AppleCL): One or more parameters passed to a function were not valid.
CSSM_ModuleLoad(): One or more parameters passed to a function were not valid.

I found a workaround on jamf forums which constantly polls the last command which shows a list of users. This can run as a Global Daemon as the same user that deadline runs under.

Bash

#!/bin/bash

crash_check=true
logged_in=false

echo "Daemon started $(date +"%Y-%m-%d %H:%M:%S") Watching for user logon and logout events..."

while true ; do

    # Case 1: If the first line of 'last' contains "reboot" and the second line contains "crash",
    # then assume the username on the "crash" line inelegantly logged out:

    crashTest=$( last -2 )
    crashTestLine1=$( echo "${crashTest}" | sed -n '1 p' | grep -i "reboot")
    crashTestLine2=$( echo "${crashTest}" | sed -n '2 p' | grep -i "crash")
    crash_user=$( echo "${crashTestLine2}" | awk -F " " '{ print $1 }' )



    # Polling interval
    sleep 1
    last_line=$( last -1 -t console )
    login_user=$( echo "${last_line}" | awk -F " " '{ print $1 }' )


    # If the status changes from a timestamp to "still logged in"
    # assume the user logged in

    # Login Check:
    if [ "$logged_in" = false ] && 
        [[ $( echo "${last_line}" | grep -i "still logged in" ) ]] ; then
        logged_in=true
        targetUser="${login_user}"
        event="login"

    # If status has changed from "still logged in"
    # to a login duration "(HH:MM)", then assume the user just logged out:

    # Logout Check:
    elif [ "$logged_in" = true ] && 
       [[ $( echo "${last_line}" | grep -i "(.*:.*)" ) ]] ; then
       logged_in=false
        targetUser="${login_user}"
        event="logout"

    # Crash Check:
    elif [[ "${crashTestLine1}" ]] && [[ "${crashTestLine2}" ]] && [ "$crash_check" = true ]; then
        crash_check=false 

        targetUser="${crash_user}"
        event="crash"

    else
        targetUser=""
    fi

    # Take action:
    if [[ "${targetUser}" ]] ; then
        echo 
        echo "$(date +"%Y-%m-%d %H:%M:%S")  User: ${targetUser} Status changed. [Event: ${event}]"

        # Get the computer name using scutil and export it to HOSTNAME
        export HOSTNAME=$(scutil --get ComputerName)

        # Logout code goes here
        if [ "$event" = "login" ]; then
            echo "Running login code..."
            /Applications/Thinkbox/Deadline10/Resources/deadlinecommand RemoteControl $HOSTNAME ForceStopSlave
            /Applications/Thinkbox/Deadline10/Resources/deadlinecommand SetSlaveSetting $HOSTNAME SlaveEnabled False
            /Applications/Thinkbox/Deadline10/Resources/deadlinecommand RemoteControl $HOSTNAME LaunchSlave
        elif [ "$event" = "logout" ]; then
            /Applications/Thinkbox/Deadline10/Resources/deadlinecommand SetSlaveSetting $HOSTNAME SlaveEnabled True
            echo "Running logout code..."

        elif [ "$event" = "crash" ]; then
            echo "Running crash code..."
        else
            echo "Invalid event"
        fi     
    fi

done

Daemon

<?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>GroupName</key>
	<string>staff</string>
	<key>InitGroups</key>
	<true/>
	<key>KeepAlive</key>
	<dict>
		<key>Crashed</key>
		<true/>
	</dict>
	<key>Label</key>
	<string>local.job</string>
	<key>ProgramArguments</key>
	<array>
		<string>/bin/sh</string>
		<string>/usr/local/bin/svad/svad_login_monitor.sh</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
	<key>StandardErrorPath</key>
	<string>/Users/Shared/svad_login-monitor_stderr.log</string>
	<key>StandardOutPath</key>
	<string>/Users/Shared/svad_login-monitor_stdout.log</string>
	<key>UserName</key>
	<string>locadmin</string>
</dict>
</plist>
1 Like
Privacy | Site terms | Cookie preferences