在 Windows 中设置定时任务并查看系统运行时间和信息

一、在 Windows 中设置定时任务

  1. 打开任务计划程序
    • Win + R,输入 taskschd.msc,然后按回车,或者通过“控制面板” > “系统和安全” > “管理工具” > “任务计划程序”来打开。
  2. 创建基本任务
    • 在任务计划程序窗口的右侧,点击“创建基本任务…”,为任务命名(例如“定时启动程序”),然后点击“下一步”。
  3. 设置任务触发器
    • 选择触发任务的频率(例如每日、每周等),然后点击“下一步”。根据需要设置具体的日期和时间。
  4. 设置任务操作
    • 在“操作”选项卡中,选择“启动程序”,然后点击“下一步”。点击“浏览”,找到要执行的快捷方式文件(.lnk 文件),并选择它。
  5. 完成任务设置
    • 查看所有设置,确保无误后点击“完成”。
  6. 测试任务
    • 在任务计划程序中找到刚创建的任务,右键点击任务名称,选择“运行”以测试任务是否正常执行。

例如,我设置的一个自动重启定时任务

image-20240823上午112430042

image-20240823上午110748238

二、查看 Windows 系统的运行时间

在 Linux 中,uptime 命令可以显示系统的运行时间。在 Windows 中,可以通过以下几种方法来查看当前机器的运行时间:

  1. 通过任务管理器查看
  • Ctrl + Shift + Esc 打开任务管理器,点击“性能”选项卡,选择左侧的“CPU”。在右侧窗口中,“上次启动时间”,这个时间表示计算机的运行时间。
  1. 通过命令提示符查看
    • Win + R,输入 cmd,然后按回车。在命令提示符中输入以下命令并按回车:
      systeminfo | find "系统启动时间"
      
    • 这会显示系统的启动时间。
  2. 通过 PowerShell 查看
    • Win + R,输入 powershell,然后按回车。输入以下命令并按回车:
      (get-date) - (gcim Win32_OperatingSystem).LastBootUpTime
      
    • 这将显示系统自启动以来的运行时间。
  3. 通过系统信息查看

    • Win + R,输入 msinfo32,然后按回车。在打开的“系统信息”窗口中,查找“系统摘要”部分的“系统启动时间”。

macOS 上的 pf 与 Linux 上的 iptables:差异与配置

在管理防火墙规则和网络包过滤时,macOS 和 Linux 系统各自采用了不同的工具。macOS 使用 pf(Packet Filter),而 Linux 则使用 iptables

这篇文章展示如何在 macOS 上配置 pf 规则以允许特定 IP 地址访问 SSH 端口。

pfiptables 的主要区别

规则处理顺序

  • iptables:按顺序处理规则,从上到下,遇到匹配的规则后就停止继续匹配。因此,规则的顺序非常重要。
  • pf:规则处理更为复杂,并不总是按顺序匹配。pf 会根据规则的类型和其他因素进行匹配,允许更加灵活的规则设置。

配置文件和语法

  • iptables:使用命令行工具进行配置,规则保存为脚本文件(通常是 bash 脚本)。配置文件不具备特定的结构。
  • pf:配置文件(通常是 /etc/pf.conf)有固定的结构和语法,更加人性化和易于管理。

功能特性

  • iptables:基于链的架构,有 filternatmangleraw 等不同的表。每个表包含若干链,每个链包含若干规则。
  • pf:支持锚(anchors)和表(tables),规则可以引用其他规则集,通过使用 scrubnatrdrqueue 等关键字提供高级功能。

pf 规则处理示例

pf 中,规则并非简单地按顺序处理:

# /etc/pf.conf 示例
block in all  # 默认阻止所有入站流量

pass in proto tcp from xx.xx.xx.xx to any port 22  # 允许特定 IP 的流量

# 其他规则...

在这个示例中,即使 block in all 在前面,后面的 pass 规则也会正确匹配并允许来自特定 IP 地址的流量连接到 22 端口。这与 iptables 的行为不同,iptables 会在遇到第一个匹配的 block 规则时停止处理。

iptables 规则处理示例

相同的规则在 iptables 中的配置如下:

# 先允许特定 IP 地址的流量
iptables -A INPUT -p tcp -s xx.xx.xx.xx --dport 22 -j ACCEPT

# 然后阻止所有其他流量
iptables -A INPUT -p tcp --dport 22 -j DROP

iptables 中,规则的顺序非常重要。我们必须先允许特定的流量,然后再阻止所有其他流量。

在 macOS 上配置 pf 规则

为了在 macOS 上设置防火墙规则,只允许特定的 IP 地址连接到 SSH 端口(22),你需要编辑 pf 配置文件,并确保这些规则在系统启动时自动应用。

默认规则:

image-20240729下午51906975

image-20240729下午54033902

pf 的 anchor 和 load anchor 类似于 iptables 的链和表,用于组织和加载规则。
pf 的 nat-anchor 和 rdr-anchor 处理 NAT 和端口重定向,类似于 iptables 的 nat 表和 PREROUTING 链。
pf 的 scrub-anchor 和 dummynet-anchor 提供类似于 iptables 的流量处理和带宽限制功能。

执行命令sudo pfctl -sr,输出是:

No ALTQ support in kernel
ALTQ related functions disabled
scrub-anchor "com.apple/*" all fragment reassemble
scrub-anchor "com.apple.internet-sharing" all fragment reassemble
anchor "com.apple/*" all
anchor "com.apple.internet-sharing" all

解释一下:

  1. No ALTQ support in kernel / ALTQ related functions disabled:
    • ALTQ(ALTernate Queueing)是用于流量整形的工具,但我的 macOS 内核没有启用对 ALTQ 的支持,因此与 ALTQ 相关的功能被禁用。
  2. scrub-anchor “com.apple/*” all fragment reassemble:
    • 这个规则表示 macOS 会对所有通过 com.apple/* 锚点的流量进行 scrub 操作。scrub 是一种重新组装 IP 分片的操作,用于处理和纠正 IP 数据包中的潜在问题。
  3. scrub-anchor “com.apple.internet-sharing” all fragment reassemble:
    • 这个规则与上一个类似,但它专门用于通过 com.apple.internet-sharing 锚点的流量。它也会对这些流量进行 scrub 操作,重新组装 IP 分片。
  4. anchor “com.apple/*” all:
    • 这个规则表示所有通过 com.apple/* 锚点的流量将被转发到与 com.apple/* 匹配的子规则进行处理。anchor 是一种将规则分组的方法,允许对特定流量应用一组规则。
  5. anchor “com.apple.internet-sharing” all:
    • 这个规则与上一个类似,但它专门用于通过 com.apple.internet-sharing 锚点的流量。这些流量将被转发到与 com.apple.internet-sharing 匹配的子规则进行处理。

这些规则主要是处理和转发由 macOS 系统创建的流量锚点和规则,特别是那些与互联网共享和其他系统功能相关的规则。

scrub 操作用于重新组装分片的 IP 数据包,以确保它们在传输过程中没有问题,

anchor 规则则用于将流量转发到特定的子规则进行进一步处理。

编辑 pf.conf 文件

  1. 打开并编辑 /etc/pf.conf 文件
    sudo vim /etc/pf.conf
    
  2. 添加新规则: 在合适的位置(例如在 scrub-anchornat-anchor 之后),在我本机上,我放到了最后一行,插入以下规则:

    block in proto tcp from any to any port 22
    pass in proto tcp from xx.xx.xx.xx to any port 22
    
  3. 保存并关闭文件

  4. 重新加载 pf 配置
    sudo pfctl -f /etc/pf.conf  # 重新加载配置
    sudo pfctl -e                # 启用 pf
    sudo pfctl -sr               # 查看当前规则以确认加载
    

在 macOS 上配置配置 pf 自启动脚本

  1. 创建启动脚本文件: 在 /usr/local/bin 目录下创建一个启动脚本文件:

    sudo vim /usr/local/bin/startup.sh
    
  2. 在脚本文件中添加以下内容
    #!/bin/bash
    
    # Enable and load pf rules
    sudo pfctl -e
    sudo pfctl -f /etc/pf.conf
    
    # 如果还有其他需求,可以一起加进来,例如增加一条路由
    sudo route -n add -net xx.xx.0.0 -netmask 255.255.0.0 xx.xx.xx.1
    
  3. 使脚本可执行

    sudo chmod +x /usr/local/bin/startup.sh
    

配置启动项:

  1. 创建 LaunchDaemon 配置文件: 在 /Library/LaunchDaemons 目录下创建一个 plist 文件:
    sudo vim /Library/LaunchDaemons/com.custom.startup.plist
    
  2. plist 文件中添加以下内容
    <?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.custom.startup</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/local/bin/startup.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <false/>
    </dict>
    </plist>
    
  3. 设置适当的权限
    sudo chown root:wheel /Library/LaunchDaemons/com.custom.startup.plist
    sudo chmod 644 /Library/LaunchDaemons/com.custom.startup.plist
    

测试和验证

  1. 加载并测试 LaunchDaemon
    sudo launchctl load /Library/LaunchDaemons/com.custom.startup.plist
    
  2. 重启电脑以验证配置: 在重启后,确保 pf 规则和路由已正确应用。可以通过以下命令检查:
    sudo pfctl -sr  # 查看当前的 pf 规则
    sudo netstat -rn     # 查看路由表
    

错误排查参考

遇到 Bootstrap failed: 5: Input/output error 错误时,可能是因为以下几个原因:

  1. 文件格式或内容问题: 确保 plist 文件的格式和内容正确。可以使用 plutil 命令验证文件格式:

    plutil -lint /Library/LaunchDaemons/com.custom.startup.plist
    

    如果文件有错误,plutil 会指出具体问题。

  2. 权限问题: 确保 plist 文件和包含该文件的目录具有正确的权限和所有权。运行以下命令:

    sudo chown root:wheel /Library/LaunchDaemons/com.custom.startup.plist
    sudo chmod 644 /Library/LaunchDaemons/com.custom.startup.plist
    
  3. 检查系统日志: 系统日志可能包含更详细的错误信息。使用以下命令查看日志:

    log show --predicate 'subsystem == "com.apple.launchservicesd"' --info --debug
    
  4. 重启 launchd 服务: 尝试重启 launchd 服务或计算机,确保所有配置生效。

    sudo launchctl unload /Library/LaunchDaemons/com.custom.startup.plist
    sudo launchctl load /Library/LaunchDaemons/com.custom.startup.plist
    
  5. 使用 launchctl bootstrap: 根据提示,可以尝试使用 launchctl bootstrap 命令来加载 plist 文件。确保以 root 身份运行此命令。

    sudo launchctl bootstrap system /Library/LaunchDaemons/com.custom.startup.plist
    

在 Mac 上将当天的日历事项导出为 TXT 文件

我经常使用Mac上的日历应用,公司每天也要写日报,于是将日历中当天的事项导出为TXT文件,可以省下很多心力做其他事情。我尝试了将近一个月,感觉不错。

本文将详细介绍如何使用 AppleScript 实现这一目标。通过简单的脚本,可以获取当天所有的日历事件,将它们导出到一个带有当前日期的TXT文件中,显示导出的记录数量。如果结合 crontab 还能完成定时自动导出的工作,甚至,结合selenium,还可以自动化填写日报。

前提条件

在开始之前,请确保你已经授予 AppleScript 访问日历的权限。如果这是你第一次运行此脚本,系统可能会提示你授权访问。

脚本说明

以下是完整的 AppleScript 脚本,确保从当天凌晨0点到当天晚上12点之间的“日常”下的所有日历事件,并将它们导出到桌面的TXT文件中。文件名将包含当前日期,并在完成导出后显示一个弹窗,告知导出的记录数量。

tell application "Calendar"
    -- 获取当前日期
    set currentDate to current date
    
    -- 设置今天的开始时间为凌晨0点
    set startOfDay to currentDate
    set time of startOfDay to 0
    
    -- 设置今天的结束时间为晚上12点
    set endOfDay to startOfDay + 1 * days

    -- 获取"日常"日历中的今天的事件
    set theEvents to (get events of calendar "日常" whose start date ≥ startOfDay and start date < endOfDay)
    
    set eventDetails to ""
    repeat with theEvent in theEvents
        set eventDetails to eventDetails & (summary of theEvent) & " - " & (start date of theEvent) & return
    end repeat
    
    -- 获取当前日期的年月日
    set {year:y, month:m, day:d} to (current date)
    set monthText to text -2 thru -1 of ("0" & (m as integer) as string)
    set dayText to text -2 thru -1 of ("0" & (d as integer) as string)
    set dateText to (y as string) & "-" & monthText & "-" & dayText
    
    -- 设置文件名
    set fileName to "daily-" & dateText & ".txt"
    
    -- 导出事件到文件
    do shell script "echo " & quoted form of eventDetails & " > ~/Desktop/" & fileName
    
    -- 显示导出记录数量的弹窗
    display dialog "导出了 " & (count of theEvents) & " 条记录。" with title "导出完成"
end tell

使用步骤

  1. 打开“脚本编辑器”: 在你的Mac上,打开“脚本编辑器”应用程序。这是macOS自带的一个应用,可以用来编写和运行AppleScript脚本。
  2. 粘贴脚本: 将上述脚本复制并粘贴到“脚本编辑器”中。
  3. 修改日历名称: 如果你使用的日历名称不是“日常”,请修改脚本中 set theEvents to (get events of calendar "日常" whose start date ≥ startOfDay and start date < endOfDay) 中的 "日常" 为你具体的日历名称。
  4. 运行脚本: 点击“运行”按钮,脚本将开始执行。

image-20240719上午90423490

修改

我做了一些细微调整:

tell application "Calendar"
	-- 获取当前日期
	set currentDate to current date
	-- 设置某个日期
	-- set currentDate to date "2024年7月23日 上午12:00:00"
	
	-- 设置今天的开始时间为凌晨0点
	set startOfDay to currentDate
	set time of startOfDay to 0
	
	-- 设置今天的结束时间为晚上12点
	set endOfDay to startOfDay + (1 * days)
	
	-- 获取"日常"日历中的今天的事件
	set theEvents to (get events of calendar "日常" whose start date ≥ startOfDay and start date < endOfDay)
	
	set eventDetails to ""
	set eventCount to count of theEvents
	set eventNumber to 1
	
	-- 构建总结性内容
	-- set summaryContent to "当前日期: " & (startOfDay as string) & " - 总共: " & eventCount & " 个日历事项" & return & return
	set summaryContent to "共" & eventCount & "个事项:" & return
	
	repeat with theEvent in theEvents
		-- 获取事件的开始时间
		set eventStartDate to start date of theEvent
		
		-- 提取时间部分并格式化
		set eventTime to time of eventStartDate
		
		-- 减去8小时调整时间,有时候有偏移,就手动改一下,没有就-0
		set adjustedTime to eventStartDate - (0 * hours)
		
		-- 格式化调整后的时间为字符串
		set timeString to (time string of adjustedTime)
		
		-- 格式化事件编号
		if eventNumber < 10 then
			set formattedNumber to "0" & eventNumber
		else
			set formattedNumber to eventNumber as string
		end if
		
		-- 构建事件详情字符串(仅内容)
		set eventDetails to eventDetails & formattedNumber & ". " & (summary of theEvent) & return
		
		-- 构建事件详情字符串(包含时间)
		-- set eventDetails to eventDetails & formattedNumber & ". " & (summary of theEvent) & " - " & timeString & return
		set eventNumber to eventNumber + 1
	end repeat
	
	-- 获取当前日期的年月日
	-- set {year:y, month:m, day:d} to (current date)
	-- 获取 startOfDay 的年月日
	set {year:y, month:m, day:d} to startOfDay
	set monthText to text -2 thru -1 of ("0" & (m as integer) as string)
	set dayText to text -2 thru -1 of ("0" & (d as integer) as string)
	set dateText to (y as string) & "-" & monthText & "-" & dayText
	
	-- 设置文件名
	set fileName to "daily-" & dateText & ".txt"
	
	-- 导出事件到文件
	-- do shell script "echo " & quoted form of (summaryContent & eventDetails) & " > ~/Desktop/" & fileName
	do shell script "echo " & quoted form of (summaryContent & eventDetails) & " > ~/Desktop/" & fileName
	
	-- 显示导出记录数量的弹窗
	-- display dialog "导出了 " & (count of theEvents) & " 条记录。" with title "导出完成"
end tell

因为平时更习惯用shell,所以我还配合写了一个shell脚本,方便 crontab 调用:

#!/bin/bash

# 获取当前年份和周数
YEAR=$(date +%y)   # 获取当前年份的最后两位,例如 24
WEEK=$(date +%V)   # 获取当前周数,例如 16

# 获取当前日期的文件名
TODAY=$(date +%Y-%m-%d)  # 格式为 YYYY-MM-DD
FILENAME="daily-${TODAY}.txt"

# 组合目录名
DIRECTORY_NAME="${YEAR}${WEEK}"

# 目标路径
TARGET_PATH="/Users/kelu/Library/Mobile Documents/com~apple~CloudDocs/${DIRECTORY_NAME}"

# 创建目录
mkdir -p "${TARGET_PATH}"

osascript "/Users/kelu/Library/Mobile Documents/com~apple~ScriptEditor2/Documents/导出今天日历.scpt"

# 源文件路径
SOURCE_FILE="/Users/kelu/Desktop/${FILENAME}"

# 移动文件
if [ -f "${SOURCE_FILE}" ]; then
    mv "${SOURCE_FILE}" "${TARGET_PATH}/"
    echo "文件已移动: ${SOURCE_FILE} -> ${TARGET_PATH}/"
else
    echo "文件未找到: ${SOURCE_FILE}"
fi

在 macOS 一次性关闭所有 chrome 实例 和 Finder 窗口

关闭 Chrome 实例

有时候自动化程序会打开很多个chrome实例,可以这样批量关闭。

  1. 打开终端。

  2. 在终端中输入以下命令并按下回车键:

    killall -9 "Google Chrome"
    

解释

  • killall 是一个用来终止所有给定进程名称的工具。
  • -9 选项表示发送SIGKILL信号,这是一个强制终止信号,告诉操作系统立即终止进程,而不进行正常的清理操作。
  • "Google Chrome" 是你要终止的应用程序的名称,记得使用双引号括起来,因为名称中有空格。

关闭所有 Finder窗口

关于 osascript 的更多内容参考我这篇文章 《使用 osascript 命令将 Mac 应用切换到前台》

osascript -e 'tell application "Finder" to close every window'

在 macOS 上为顶级域名设置特定的 DNS 服务器

有好些方式,例如自建dns,就是最灵活的解决方案。如果不需要那么多的特性,可以通过配置 resolver 文件,可以为特定的域名甚至顶级域名设置特定的 DNS 服务器。本文将介绍如何为顶级域名 .abc 设置使用 DNS 服务器 1.2.3.4

步骤 1:创建 resolver 文件夹

首先,需要确保 /etc/resolver 文件夹存在。这个文件夹将存放特定域名的 DNS 配置文件。

打开终端并运行以下命令:

sudo mkdir -p /etc/resolver

步骤 2:为顶级域名 .abc 创建配置文件

接下来,我们需要为顶级域名 .abc 创建一个配置文件。在终端中运行以下命令创建并编辑配置文件:

sudo vim /etc/resolver/abc

在文件中添加以下内容:

nameserver 1.2.3.4

步骤 3:测试配置

配置完成后,可以通过以下命令测试 DNS 配置是否生效:

nslookup example.abc

结果应该显示 DNS 查询是通过 1.2.3.4 进行的:

Server:         1.2.3.4
Address:        1.2.3.4#53

Non-authoritative answer:
Name:   example.abc
Address: <IP_ADDRESS>

防止AirPods 自动连接至 Mac/iPhone/iPad

在Mac上:

  1. 打开“系统设置”(macOS Ventura 及以上版本)或“系统偏好设置”(macOS Monterey 及以下版本)。

  2. 选择“AirPods”

    image-20240617上午82139846

  3. 在“连接到此Mac”选项下,不选择自动,选择“上次连接到此Mac时。

  4. 选择后,如果断开AirPods,就找不到这个侧边栏选项了。

  5. iPhone iPad也是类似。

    IMG_8078


1 2 3 4 5 6 7 161 162