Reputation: 1
I run a computer lab with Macintosh devices and need to enable auto logout functionality when users are idle. Unfortunately, the built-in function to do this in the operating system does not work properly if users leave unsaved documents open; it just hangs asking if they want to save.
To work around this, I created a script with the intention of force restarting the computer when sessions are idle instead, but I want to prompt them with a message first so they can prevent the restart if they are still sitting at the computer. If they don't respond, then it should restart.
However, I've run into issues with this at every turn and I am about to rip my hair out. The code itself is written in Python, and specifically, the issue I am running into is always with the message box. The code runs fine when run manually, but if I run the script as a LaunchAgent (/Library/LaunchAgents), I encounter different issues depending on the functions used to create the message box. I've tried osascript, Tkinter, and PyQt6.
FYI, I have modified the sudoers file to grant all users access to run "/sbin/reboot -q" to accommodate the restarts. When run manually, the restarts work regardless of user account.
Script code:
#!/usr/bin/env python3
import shlex
import subprocess
# Time in seconds
IDLE_TIME = 60 # Set low for testing purposes
def get_idle_time():
try:
output = subprocess.check_output("ioreg -c IOHIDSystem | grep -i 'HIDIdleTime'", shell=True)
output_str = output.decode()
print(f"Raw output from ioreg: {output_str}") # Debugging line
lines = output_str.splitlines()
for line in lines:
if 'HIDIdleTime' in line:
parts = line.split('=')
if len(parts) == 2:
idle_time_str = parts[1].strip()
idle_time = int(idle_time_str)
return idle_time / 1_000_000_000 # Convert nanoseconds to seconds
print("HIDIdleTime not found in output")
return 0
except Exception as e:
print(f"Error getting idle time: {e}")
return 0
def notify_users():
script = '''
tell application "System Events"
set dialogResult to (display alert "The system has been idle for 15 minutes and will reboot in 1 minute.\n\nDo you want to cancel the reboot?" as critical buttons {"No", "Yes"} default button "No" giving up after 60)
if button returned of dialogResult is "Yes" then
return "Cancel"
else
return "Reboot"
end if
end tell
'''
try:
result = subprocess.check_output(["osascript", "-e", script]).decode().strip()
print(f"AppleScript output: {result}") # Debugging line
return result
except subprocess.CalledProcessError as e:
print(f"AppleScript error: {e}")
return "Error"
except Exception as e:
print(f"Unexpected error: {e}")
return "Error"
def main():
idle_seconds = get_idle_time()
if idle_seconds > IDLE_TIME:
user_response = notify_users()
print(f"User response was: {user_response}")
if user_response == "Reboot":
print("Reboot should have happened")
# Next lines disabled to prevent actual restart from occurring while debugging
# args = shlex.split('sudo -u root reboot -q')
# process = subprocess.Popen(args, shell=False)
# process.communicate()
elif user_response == "Cancel":
print("Reboot cancelled by the user.")
else:
print("System is not idle enough for a reboot.")
if __name__ == "__main__":
main()
osascript - works great... after I grant python3 permissions to control System Events with a pop-up that comes up at the first run of the script under each user account. I've tried granting python3 permission in System Preferences > Security & Privacy > Privacy > Accessibility as many online recommend, but this didn't work. I feel like this would be the best option if I could get this permission request to not pop up every time the script runs.
Tkinter - works great when run manually. However, once I enable it as a LaunchAgent, the text label is not visible and the .after() countdown timer doesn't seem to work. It just hangs. Buttons show up fine, so I tried just using a single button instead of a text label, but the countdown timer for .after() still doesn't work right.
PyQt - works great when run manually. However, the message box never comes up if run as a LaunchAgent.
Since the osascript option for the message box is probably best, I'll post the code here for that version of the script and hope someone can help me get rid of the permission request notification.
Warning I get with osascript:
"python3" wants access to control "System Events". Allowing control will provide access to documents and data in "System Events", and to perform actions within that app.
Upvotes: 0
Views: 42