Created
October 22, 2021 09:16
-
-
Save hexiyou/5e62b68432b77b7804c678116f94f918 to your computer and use it in GitHub Desktop.
delayexec.sh:Cygwin下专用Bash脚本,配合schtasks方便快捷从命令行创建Windows任务计划,仅运行一次,支持多种时间格式参数指定运行时间,可调用任何cmd命令和Cygwin下的命令。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#Windows计划任务cron脚本,通过任务计划调用Cygwin执行某命令 | |
## Example: | |
## 1. delayexec 3600 tplink #延迟3600秒(1小时)运行tplink | |
## 2. delayexec 05:30 tplink #定时5点半运行tplink,自动识别日期,当前时刻早于指定时间,则当天执行,当前时刻晚于指定时间,则次日执行 | |
## 3. delayexec ++07:30 tplink #两天后的七点半运行命令tplink,此模式用以显式指定日期,一个+号代表延期一天,可以重复叠加,+代表1天后,+++代表3天后 | |
## 4. delayexec '12-31 15:30' killpm tplink #指定今年12月31号下午三点半退出tplink进程(缺省年份自动设定为今年) | |
## 5. delayexec '2025-12-24 15:30' killpm tplink #指定2025年12月24号下午三点半退出tplink进程(其中年月日分隔符也可省略) | |
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天" | |
echo -e "--------\n" | |
echo -e "高级用法:\n\t可直接指定完整的日期和时间(年份可省略,省略年份时,自动补齐为当前年份):" | |
echo -e "\t- 格式一:“[年-]月-日 时:分[:秒]”\t eg:【2022-09-18 15:33:12】 或 【09-18 15:33】" | |
echo -e "\t- 格式二:“[年]月日 时:分[:秒]”\t\t eg:【20220918 15:33:12】 或 【0918 15:33】" | |
echo -e "\x20Example4:\n\tdelayexec '2022-12-24 15:30' killpm tplink" | |
echo -e "\t- 指定2022年12月24日下午三点半运行命令退出tplink进程;" | |
echo -e "\x20Example5:\n\tdelayexec '20221224 15:30' killpm tplink" | |
echo -e "\t- 同上,缩减了日期中间的短横线分隔符,2022年12月24日下午三点半退出tplink进程;" | |
echo -e "\x20Example6:\n\tdelayexec '12-31 15:30' killpm tplink" | |
echo -e "\t- 指定今年12月31号下午三点半退出tplink进程(缺省年份自动设定为今年);" | |
echo -e "\x20Example7:\n\tdelayexec '1231 15:30' killpm tplink" | |
echo -e "\t- 同上,缩减了日期分隔符,今年12月31号下午三点半退出tplink进程;" | |
echo -e "\n\t- 注:在年月日没有分隔符的情况下,推荐月日最好为4位数,尽管程序对三位数月日进行了部分适配(不带年份时),但月份数位数为单时请手动前面补零,否则 \`date\` 命令无法正确处理。" | |
} | |
# 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})?$ || "$1" =~ ^([0-9]{4}-)?([0-9]{1,2}-[0-9]{2} )?[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?$ || "$1" =~ ^([0-9]{4})?([0-9]{1,2}[0-9]{2} )?[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 | |
fixDateTime="$1" | |
fixDate=$(echo "$fixDateTime"|awk -F ' ' 'NF<2{exit}{print $1}') | |
#echo "fixDate:$fixDate" | |
if [[ "$fixDateTime" =~ "-" ]] && [ ${#fixDate} -gt 0 -a ${#fixDate} -lt 9 ] | |
then | |
fixDateTime="$(date +'%Y-')${fixDateTime}" | |
elif [[ "$fixDate" =~ ^(0[1-9]|[1][0-2]{1})[0-3][0-9]$ ]] #匹配四位数月日,eg:0921,1128,1205... | |
then | |
fixDateTime="$(date +'%Y')${fixDateTime}" | |
elif [[ "$fixDate" =~ ^[1-9][0-3][0-9]$ ]] #匹配月份位数为单数的情况,eg:810,922... | |
then | |
fixDateTime="$(date +'%Y0')${fixDateTime}" | |
elif [ ${#fixDate} -ne 0 -a ${#fixDate} -le 4 ] | |
then | |
echo "日期时间参数:“${fixDateTime}” 解析失败,因日期 “${fixDate}” 不在有效范围,脚本退出..." | |
exit 1 | |
fi | |
[ $(date +'%s') -ge $(date -d "$fixDateTime" +'%s' 2>/dev/null) ] &>/dev/null | |
increDay=$? | |
[ $increDay -eq 2 ] && { | |
echo "参数无效:“${fixDateTime}” 指定的日期时间无效,脚本退出..." | |
exit 1 | |
} | |
[ ! -z "$fixDate" ] && increDay=1 | |
executeTime=$(getClockExecTime $increDay "$fixDateTime") | |
#[ $(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..." |
Author
hexiyou
commented
Oct 22, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment