苹果笔记本实现用户登录钉钉通知功能
苹果笔记本实现用户登录钉钉通知功能需求描述公司有台苹果电脑会有多个用户使用。经常出现相互争抢的情况。所以计划实现以下功能：有用户登陆或者退出的时候发送通知消息到钉钉群。这样大家需要用电脑的时候先查询一下当前是否有用户在用，避免争抢。思路：添加系统的后台开机自启动任务，系统启动的时候，执行一个常驻后台任务，监控系统用户状态。有用户登陆的时候，发送消息到钉钉群。系统环境：MacOS 13.5系统账号：wiyigg创建mac守护进程配置以root权限在创建并编辑/Library/LaunchDaemons/com.test.loginevent.plist 文件，内容如下:<?xml version="1.0" encoding="UTF-8"?> Label com.test.loginevent ProgramArguments /usr/bin/python3 /usr/local/bin/logout.py RunAtLoad <true/> KeepAlive <false/> StandardOutPath /var/log/logout.stdout.log StandardErrorPath /var/log/logout.stderr.log 其中一下三行需要注意：com.test.loginevent //此程序功能注册后的名称，稍后用到/Users/wiyigg/myvenv/bin/python3.12 //python3程序路径，由于系统版本问题，所以另行安装了python3.12需要使用更高版本的python3.12虚拟环境，创建路径如上/usr/local/bin/logout.py //真正后台运行的python程序sudo mkdir /usr/local/bin编写后台程序Python脚本cat /usr/local/bin/logout.py#coding: utf-8 #代码中的 dingtalk_webhook_url 改成自己的钉钉群机器人webhook #"senderNick": "Hostname" Hostname是自己的电脑名字，用来标识的，对应修改 import subprocess import time import requests import json import socket from datetime import datetime # 钉钉Webhook URL 这里配置了运维业务报警群的机器人用于测试，后面根据需求进行修改 dingtalk_webhook_url = 'https//:xxxxxx' # 获取当前登录的用户列表 def get_logged_in_users(): try: # 使用 'who' 命令获取当前登录的用户 users_output = subprocess.check_output(['who'], text=True) users = set(line.split()[0] for line in users_output.strip().split('\n') if line) return users except subprocess.CalledProcessError as e: print(f"Error retrieving logged in users: {e}") return set() # 发送钉钉消息 def send_dingtalk_message(message): headers = {'Content-Type': 'application/json'} data = { "msgtype": "text", "text": { "content": message }, "senderNick": "Hostname" #这里是固定值，需要修改与当前主机一致 } try: response = requests.post(dingtalk_webhook_url, headers=headers, data=json.dumps(data)) except: return 0 #if response.status_code == 200: # print("Message sent to DingTalk successfully.") #else: # print(f"Failed to send message to DingTalk: {response.text}") # 存储上次登录的用户列表 last_logged_in_users = get_logged_in_users() # 主循环 while True: # 获取当前登录的用户列表 current_logged_in_users = get_logged_in_users() # 查找注销的账号 logged_out_users = last_logged_in_users - current_logged_in_users # 查找新登录的账号 logged_in_users = current_logged_in_users - last_logged_in_users # 获取主机名 hostname = socket.gethostname() # 获取当前时间 now = datetime.now() formatted_now = now.strftime("%Y-%m-%d %H:%M:%S") # 如果有账号注销，则发送钉钉消息 if logged_out_users: message = f" 登出{', '.join(logged_out_users)}" send_dingtalk_message(message) # 如果有新用户登录，则发送钉钉消息 if logged_in_users: message = f" 登入{', '.join(logged_in_users)}" send_dingtalk_message(message) # 更新上次登录的用户列表 last_logged_in_users = current_logged_in_users # 每隔3秒执行一次，可以根据需求调整 time.sleep(3)配置python虚拟环境使用系统的brew安装 python3.12如果系统没有brew命令先安装brew软件，然后安装python3.12#安装brew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装python3.12brew install python@3.12 设置python3.12虚拟环境 /usr/local/bin/python3.12 -m venv myvenv 会创建 /Users/wiyigg/myvenv目录 激活虚拟环境 source /Users/wiyigg/myvenv/bin/activate 然后在虚拟环境中安装pip3模块 本次依赖外部模块有 requests pip3 install requests这里解释下为什么要用python虚拟环境，因为macOS 13.5当前自带最新版本python3.9.5(时间2024.07.29) 执行 /usr/local/bin/logout.py 会出现警告，虽然脚本能够执行成功，但是在后台跑的时候这个警告会导致后台任务执行失败。我当时排查了好久才定位到是这个警告导致的程序不运行。汗~~~！！！切换到虚拟环境后，不报警告，并且能成功执行然后就是添加系统后台任务，并且启动服务测试了。# 加载守护进程配置 #加载的时候要使用绝对路径，反复加载会报错，只有第一次加载能成功 sudo launchctl load /Library/LaunchDaemons/com.test.loginevent.plist # 启动守护进程 sudo launchctl start com.test.loginevent.plist # 查看进程是否启动 ps ax | grep logout代码中的 dingtalk_webhook_url 改成自己的钉钉群机器人webhook，即可然后就可以登录和等出测试啦.