脚本用法:
/v/bin/delayexec 创建Windows任务计划,延迟或定时执行Cygwin下某命令. 注:本脚本创建的任务计划仅执行一次,不会重复调用,如果需要周期性反复执行的命令,请手动创建任务计划或使用`schtasks`命令来创建; Usage: delayexec delaytime-Seconds|time-clock(时:分:秒) command argument1 argument2 ... Example1: delayexec 3600 tplink - 延迟3600秒(1小时)执行tplink Example2: delayexec 05:30 recordlive-bilibili 7200 - 今天或次日5点半(取决于现在时刻早于还是晚于指定的时间)执行recordlive-bilibili录制视频两小时 Example3: delayexec ++07:30 killpm tplink - 两天后的7点半退出tplink进程,+号指定延迟的天数,+可叠加使用,如+++代表当前日期后延3天
代码如下:
#!/bin/bash #Windows计划任务cron脚本,通过任务计划调用Cygwin执行某命令 ## Example: ## 1. delayexec 3600 tplink #延迟3600秒(1小时)运行tplink ## 2. delayexec 05:30 tplink #定时5点半运行tplink,自动识别日期,当前时刻早于指定时间,则当天执行,当前时刻晚于指定时间,则次日执行 ## 2. delayexec ++07:30 tplink #两天后的七点半运行命令tplink,此模式用以显式指定日期,一个+号代表延期一天,可以重复叠加,+代表1天后,+++代表3天后 SCRIPTPATH=$(realpath $0) display_usage() { echo -e "$SCRIPTPATH\n" echo -e "\t创建Windows任务计划,延迟或定时执行Cygwin下某命令." echo -e "\t注:本脚本创建的任务计划仅执行一次,不会重复调用,如果需要周期性反复执行的命令,请手动创建任务计划或使用\`schtasks\`命令来创建;" echo -e "\nUsage:\n\tdelayexec delaytime-Seconds|time-clock(时:分:秒) command argument1 argument2 ..." echo -e "Example1:\n\tdelayexec 3600 tplink" echo -e "\t- 延迟3600秒(1小时)执行tplink" echo -e "Example2:\n\tdelayexec 05:30 recordlive-bilibili 7200" echo -e "\t- 今天或次日5点半(取决于现在时刻早于还是晚于指定的时间)执行recordlive-bilibili录制视频两小时" echo -e "Example3:\n\tdelayexec ++07:30 killpm tplink" echo -e "\t- 两天后的7点半退出tplink进程,+号指定延迟的天数,+可叠加使用,如+++代表当前日期后延3天" } # if less than two arguments supplied, display usage if [ $# -lt 1 ] then display_usage exit 1 fi # check whether user had supplied -h or --help . If yes display usage if [[ ( $* == "--help") || $* == "-h" ]] then display_usage exit 0 fi getDelayExecTime() { # 参数$1传递需要延迟执行任务计划的时间,单位为秒 #local updateTime=$(date -d "1970-01-01 UTC ${1} seconds +3 minutes" +'%Y-%m-%dT%H:%M:%S') local updateTime=$(date -d "+${1} Seconds" +'%Y-%m-%dT%H:%M:%S') echo "$updateTime" } getClockExecTime() { # 参数$1传递执行任务计划的准确时刻,示例:14:25 case $1 in 0) local executeTime=$(date -d "+1day $2" +'%Y-%m-%dT%H:%M:%S') ;; *) local executeTime=$(date -d "$2" +'%Y-%m-%dT%H:%M:%S') ;; esac echo "$executeTime" } #说明:以下为什么要用两个模板文件,为什么要先导出XML再更改,主要考虑是为了更好的兼容性,比如更换电脑后,用户Sid改变导致任务计划不能按预期效果执行,此故障到底会不会发生未经严格测试,仅此以防万一 schTasksXML="/v/reg-tpl/update-delayexec-schtasks.xml" schTasksXMLInitFile="/v/reg-tpl/update-delayexec-schtasks-init.xml" #默认延迟时间:3600秒 delayTimeSec=3600 #执行命令的时间: executeTime=-1 #脚本 $1 供外部传递延迟时间,参数类型正整数,单位为秒 if [ ! -z "$1" ] then expr $1 + 0 &>/dev/null if [ $? -eq 0 ] then delayTimeSec=$1 shift elif [[ "$1" =~ ^(\++)?[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?$ ]] then delayDays=0 #处理时间参数传递+号的情况,+号可重复叠加使用,如:++00:30 表示两天后的夜里12点半。 while read -n 1 char ; do if [ "$char" != "+" ] then break fi let delayDays+=1 done <<<"$1" if [ $delayDays -eq 0 ] then [ $(date +'%s') -ge $(date -d "$1" +'%s') ] executeTime=$(getClockExecTime $? "$1") delayTimeSec=-1 else timeExpression="+ ${delayDays} days ${1//+/}" executeTime=$(getClockExecTime 1 "$timeExpression") delayTimeSec=-1 fi shift fi fi #预备执行的命令: prepareExecCommand="$*" [ -z "$prepareExecCommand" ] && { echo "待执行命令为空,脚本退出..." exit 0 } #XML使用的计划任务名称: schtasksTitle="${*//\//_}" #schtasksTitle="$1" [ "$executeTime" = "-1" ] && executeTime=$(getDelayExecTime $delayTimeSec) [ $delayTimeSec -ne -1 ] && echo "延迟 $delayTimeSec 秒后执行命令:${prepareExecCommand}" echo "执行时间:$(date -d "${executeTime}" +'%Y-%m-%d %H:%M:%S')" #exit 0 #Test:中断 schtasksURI='\\Cygwin自用\\定时执行命令:'"${schtasksTitle}" #导出最新的定时执行命令的任务计划模板: gsudo SCHTASKS /Query /TN "${schtasksURI//\\\\/\\}" /XML ONE >$(cygpath -aw "$schTasksXML") 2>/dev/null #如果XML文件大小为零,即计划任务管理器没有该任务,则从预先准备的最原始的XML文件读取任务计划信息: if [ "$(stat -c '%s' $schTasksXML)" == "0" ] then #echo "指定的任务计划不存在!" #exit 0 schTasksXML=$schTasksXMLInitFile fi #替换任务唤醒时间为指定时间,并去掉禁用任务的标识(如果任务被禁用的话): awk -i inplace '/<URI>/{getline;print "<URI>'"${schtasksURI}"'</URI>"}/StartBoundary/{getline;print "\t<StartBoundary>'${executeTime}'</StartBoundary>"}/<Enabled>false/{getline;}/<Arguments>/{getline;print "\t<Arguments>'"${prepareExecCommand}"'</Arguments>"}{print}' $schTasksXML #cat $schTasksXML #导入XML文件到计划任务: gsudo SCHTASKS /Create /F /XML $(cygpath -aw "$schTasksXML") /TN "${schtasksURI//\\\\/\\}" echo -e "Done..."
帮助信息截图:
运行结果截图:
附件:XML文件 update-delayexec-schtasks-init.xml 之模板代码如下:
<?xml version="1.0" encoding="UTF-16"?> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2021-09-29T14:45:34.6728472</Date> <Author>DESKTOP-ENTJJOK\Administrator</Author> <URI>\Cygwin����\��ʱִ�����tplink</URI> </RegistrationInfo> <Principals> <Principal id="Author"> <UserId>S-1-5-21-1929780610-3846960160-3848736843-500</UserId> <LogonType>InteractiveToken</LogonType> </Principal> </Principals> <Settings> <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> </Settings> <Triggers> <TimeTrigger> <StartBoundary>2021-10-19T12:00:00</StartBoundary> </TimeTrigger> </Triggers> <Actions Context="Author"> <Exec> <Command>D:\Extra_bin\cygwin-hide.exe</Command> <Arguments>tplink</Arguments> </Exec> </Actions> </Task>