重新安排工作

发布于 2024-10-04 13:43:02 字数 93 浏览 9 评论 0原文

有没有办法更改使用 unix at 命令发出的作业的日期?

我需要这样做,因为我的应用程序同时安排了太多作业,这将使机器停止运行。

Is there a way to change the date of a job that has been issued with the unix at command?

I need to do this because my Application has scheduled too many jobs at the same time which will bring the machine to a grinding halt.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

花心好男孩 2024-10-11 13:43:02

这可能与实现相关,但在我的系统上,我可以像这样重命名作业:

$ # Bash
$ sudo ls -l /var/spool/cron/atjobs
-rwx------ 1 username daemon 3782 Nov 29 11:24 a00078014854e8
$ atq
120     Mon Nov 29 11:44:00 2010 a username
$ printf "%x\n" $((16#14854e8 + 60*2))    # 2 hour delay
1485560
$ sudo mv /var/spool/cron/atjobs/a00078014854e8 /var/spool/cron/atjobs/a0007801485560
$ atq
120     Mon Nov 29 13:44:00 2010 a username

文件名中的最后 8 个十六进制数字是 Unix 纪元的分钟数,决定运行作业的时间。将其增加延迟的分钟数。

编辑:

下面是一个 Bash 脚本,用于自动执行上述步骤。以下是一些运行示例:

创建作业:

$ date
Mon Nov 29 20:00:00 CST 2010
$ echo true | at now + 1 hour
$ atq
140     Mon Nov 29 21:00:00 2010 a username

将作业重新安排为一小时后:

$ sudo atrs 140 60
Job 140 in Queue "a" rescheduled
from Mon Nov 29 21:00:00 CST 2010
to   Mon Nov 29 22:00:00 CST 2010

将其重新安排为提前 15 分钟:

$ sudo atrs 140 -15
Job 140 in Queue "a" rescheduled
from Mon Nov 29 22:00:00 CST 2010
to   Mon Nov 29 21:45:00 CST 2010

现在添加一天:

$ sudo atrs 140 $((60 * 24))
Job 140 in Queue "a" rescheduled
from Mon Nov 29 21:45:00 CST 2010
to   Mon Nov 30 21:45:00 CST 2010

您可以指定一个队列:

$ sudo atrs -q b 141 120

进行一次试运行:

$ sudo atrs -n 140 30
Job 140 in Queue "a"
Current  job time: Mon Nov 30 21:45:00 2010
Proposed job time: Mon Nov 30 22:15:00 2010

以下是脚本:

#!/bin/bash
# atrs - reschedule at jobs
# atrs [-n] [-q queue] job [-|+]minutes

# by Dennis Williamson 2010-11-29
# in response to http://stackoverflow.com/questions/4304631/rescheduling-an-at-job

# for Bash 3.2 or greater

# this script assumes that the last eight characters of the at job filename is
# a sequence of hex digits representing the number of minutes starting at
# the Unix epoch that is the time that the job is scheduled to be run

LC_COLLATE=C
export LC_TIME=C
shopt -s nullglob

mvcmd=/bin/mv
datecmd=/bin/date
GREP_OPTIONS=
grepcmd=/bin/grep
atqcmd=/usr/bin/atq

atjobs=/var/spool/cron/atjobs

declare -r tab=
\t'
declare -r NOEXIT=0
declare -r EXIT=1
# it's not necessary to bitmap the errors, but I just wanted to
declare -r ERROPTS=1
declare -r ERROARG=2
declare -r ERRARGS=4
declare -r ERRQUNM=8
declare -r ERRNOJB=16
declare -r ERRMVFL=32
declare -r ERRNOCH=64
declare -r ERRNINT=128
declare -r DRYRUN=255   # not otherwise possible to reach this number

queue=a
err=0

error () {
    (( err |= ${2:-0} ))
    msg+="${3:+$3\n}"
    if (( $1 == $EXIT ))
    then
        printf "$msg"
        printf "Usage: ${0##*/} [-n] [-q queue] job [-|+]minutes\n"
        printf "       the default queue is a\n"
        printf "       -n = dry run (default if not superuser)\n"
        exit $err
    else
        return

    fi
}

# Process options and arguments
options=':q:nh'
while getopts $options option
do
    case $option in
        q  )    queue=$OPTARG;;
        n  )    execute=1; ret=$DRYRUN;; # do dry run
        h  )    error $EXIT $DRYRUN;;
        \? )    if (( (err & ERROPTS) != ERROPTS ))
                then
                    error $NOEXIT $ERROPTS "Unknown option."
                fi;;
        *  )    error $NOEXIT $ERROARG "Missing option argument.";;
    esac
done

shift $(($OPTIND - 1))

if [[ ! $queue =~ ^[a-zA-Z=]$ ]]
then
    error $NOEXIT $ERRQUNM "Invalid queue name."
fi

if (( $# != 2 ))
then
    error $NOEXIT $ERRARGS "Job number and offset in minutes are required."
fi

if [[ $1 =~ ^[0-9]+$ ]]
then
    job=$1
else
    error $NOEXIT $ERRNINT "Job number must be a positive integer."
fi

if [[ $2 =~ ^[-+]?[0-9]+$ ]]
then
    minutes=$2
else
    error $NOEXIT $ERRNINT "Minutes must be an integer."
fi

if (( err != 0 ))
then
    error $EXIT
fi

# make preparations
if (( $EUID == 0 ))
then
    printf -v old "%05x" "$job"
    prefix="$atjobs/$queue$old"
    file=($prefix*)
    if [[ -z $file || ! -e $file ]]
    then
        error $EXIT $ERRNOJB "Job not found."
    fi
    oldhex="${file#$prefix}"
    oldminutes=$((16#$oldhex))
    newminutes=$((oldminutes + minutes))
    printf -v newhex "%08x" "$newminutes"

    from=$($datecmd -d @"$(($oldminutes * 60))")
    to=$($datecmd -d @"$((newminutes * 60))")
else
    if (( execute == 0 ))
    then
        printf "You must be superuser to reschedule jobs. The job will be listed instead.\n"
        execute=1 # do dry run
        ret=$DRYRUN
    fi
fi

# perform action
if (( execute == 0 ))
then
    if [[ $file != $prefix$newhex ]]
    then
        if $mvcmd "$file" "$prefix$newhex"
        then
            printf 'Job %s in Queue "%s" rescheduled\n' "$job" "$queue"
            printf "from %s\n" "$from"
            printf "to   %s\n" "$to"
        else
            error $EXIT $ERRMVFL "Reschedule failed."
        fi
    else
        error $EXIT $ERRNOCH "No change, times are the same."
    fi
else
    jobdate=$($atqcmd -q $queue | $grepcmd "^$job$tab")
    if [[ -n $jobdate ]]
    then
        jobdate=${jobdate#$job$tab}
        jobdate=${jobdate%% $queue *}
        newjobdate=$($datecmd +%c -d "$jobdate + $minutes minutes")
        if [[ $jobdate != $newjobdate ]]
        then
            printf 'Job %s in Queue "%s"\n' "$job" "$queue"
            printf "Current  job time: %s\n" "$jobdate"
            printf "Proposed job time: %s\n" "$newjobdate"
        else
            error $EXIT $ERRNOCH "Proposed time would result in no change."
        fi
    else
        error $EXIT $ERRNOJB "Job not found."
    fi
fi

exit $ret

This is probably implementation dependent, but on my system I can rename the job like so:

$ # Bash
$ sudo ls -l /var/spool/cron/atjobs
-rwx------ 1 username daemon 3782 Nov 29 11:24 a00078014854e8
$ atq
120     Mon Nov 29 11:44:00 2010 a username
$ printf "%x\n" $((16#14854e8 + 60*2))    # 2 hour delay
1485560
$ sudo mv /var/spool/cron/atjobs/a00078014854e8 /var/spool/cron/atjobs/a0007801485560
$ atq
120     Mon Nov 29 13:44:00 2010 a username

The last 8 hex digits in the filename is the number of minutes from the Unix Epoch that determines the time to run the job. Increment that by the number of minutes to delay.

Edit:

Below is a Bash script to automate the steps above. Here are some example runs:

Create a job:

$ date
Mon Nov 29 20:00:00 CST 2010
$ echo true | at now + 1 hour
$ atq
140     Mon Nov 29 21:00:00 2010 a username

Reschedule the job for one hour later:

$ sudo atrs 140 60
Job 140 in Queue "a" rescheduled
from Mon Nov 29 21:00:00 CST 2010
to   Mon Nov 29 22:00:00 CST 2010

Reschedule it for 15 minutes earlier:

$ sudo atrs 140 -15
Job 140 in Queue "a" rescheduled
from Mon Nov 29 22:00:00 CST 2010
to   Mon Nov 29 21:45:00 CST 2010

Now add a day:

$ sudo atrs 140 $((60 * 24))
Job 140 in Queue "a" rescheduled
from Mon Nov 29 21:45:00 CST 2010
to   Mon Nov 30 21:45:00 CST 2010

You can specify a queue:

$ sudo atrs -q b 141 120

Do a dry run:

$ sudo atrs -n 140 30
Job 140 in Queue "a"
Current  job time: Mon Nov 30 21:45:00 2010
Proposed job time: Mon Nov 30 22:15:00 2010

Here's the script:

#!/bin/bash
# atrs - reschedule at jobs
# atrs [-n] [-q queue] job [-|+]minutes

# by Dennis Williamson 2010-11-29
# in response to http://stackoverflow.com/questions/4304631/rescheduling-an-at-job

# for Bash 3.2 or greater

# this script assumes that the last eight characters of the at job filename is
# a sequence of hex digits representing the number of minutes starting at
# the Unix epoch that is the time that the job is scheduled to be run

LC_COLLATE=C
export LC_TIME=C
shopt -s nullglob

mvcmd=/bin/mv
datecmd=/bin/date
GREP_OPTIONS=
grepcmd=/bin/grep
atqcmd=/usr/bin/atq

atjobs=/var/spool/cron/atjobs

declare -r tab=
\t'
declare -r NOEXIT=0
declare -r EXIT=1
# it's not necessary to bitmap the errors, but I just wanted to
declare -r ERROPTS=1
declare -r ERROARG=2
declare -r ERRARGS=4
declare -r ERRQUNM=8
declare -r ERRNOJB=16
declare -r ERRMVFL=32
declare -r ERRNOCH=64
declare -r ERRNINT=128
declare -r DRYRUN=255   # not otherwise possible to reach this number

queue=a
err=0

error () {
    (( err |= ${2:-0} ))
    msg+="${3:+$3\n}"
    if (( $1 == $EXIT ))
    then
        printf "$msg"
        printf "Usage: ${0##*/} [-n] [-q queue] job [-|+]minutes\n"
        printf "       the default queue is a\n"
        printf "       -n = dry run (default if not superuser)\n"
        exit $err
    else
        return

    fi
}

# Process options and arguments
options=':q:nh'
while getopts $options option
do
    case $option in
        q  )    queue=$OPTARG;;
        n  )    execute=1; ret=$DRYRUN;; # do dry run
        h  )    error $EXIT $DRYRUN;;
        \? )    if (( (err & ERROPTS) != ERROPTS ))
                then
                    error $NOEXIT $ERROPTS "Unknown option."
                fi;;
        *  )    error $NOEXIT $ERROARG "Missing option argument.";;
    esac
done

shift $(($OPTIND - 1))

if [[ ! $queue =~ ^[a-zA-Z=]$ ]]
then
    error $NOEXIT $ERRQUNM "Invalid queue name."
fi

if (( $# != 2 ))
then
    error $NOEXIT $ERRARGS "Job number and offset in minutes are required."
fi

if [[ $1 =~ ^[0-9]+$ ]]
then
    job=$1
else
    error $NOEXIT $ERRNINT "Job number must be a positive integer."
fi

if [[ $2 =~ ^[-+]?[0-9]+$ ]]
then
    minutes=$2
else
    error $NOEXIT $ERRNINT "Minutes must be an integer."
fi

if (( err != 0 ))
then
    error $EXIT
fi

# make preparations
if (( $EUID == 0 ))
then
    printf -v old "%05x" "$job"
    prefix="$atjobs/$queue$old"
    file=($prefix*)
    if [[ -z $file || ! -e $file ]]
    then
        error $EXIT $ERRNOJB "Job not found."
    fi
    oldhex="${file#$prefix}"
    oldminutes=$((16#$oldhex))
    newminutes=$((oldminutes + minutes))
    printf -v newhex "%08x" "$newminutes"

    from=$($datecmd -d @"$(($oldminutes * 60))")
    to=$($datecmd -d @"$((newminutes * 60))")
else
    if (( execute == 0 ))
    then
        printf "You must be superuser to reschedule jobs. The job will be listed instead.\n"
        execute=1 # do dry run
        ret=$DRYRUN
    fi
fi

# perform action
if (( execute == 0 ))
then
    if [[ $file != $prefix$newhex ]]
    then
        if $mvcmd "$file" "$prefix$newhex"
        then
            printf 'Job %s in Queue "%s" rescheduled\n' "$job" "$queue"
            printf "from %s\n" "$from"
            printf "to   %s\n" "$to"
        else
            error $EXIT $ERRMVFL "Reschedule failed."
        fi
    else
        error $EXIT $ERRNOCH "No change, times are the same."
    fi
else
    jobdate=$($atqcmd -q $queue | $grepcmd "^$job$tab")
    if [[ -n $jobdate ]]
    then
        jobdate=${jobdate#$job$tab}
        jobdate=${jobdate%% $queue *}
        newjobdate=$($datecmd +%c -d "$jobdate + $minutes minutes")
        if [[ $jobdate != $newjobdate ]]
        then
            printf 'Job %s in Queue "%s"\n' "$job" "$queue"
            printf "Current  job time: %s\n" "$jobdate"
            printf "Proposed job time: %s\n" "$newjobdate"
        else
            error $EXIT $ERRNOCH "Proposed time would result in no change."
        fi
    else
        error $EXIT $ERRNOJB "Job not found."
    fi
fi

exit $ret
烟燃烟灭 2024-10-11 13:43:02

这将为该作业分配一个新时间的新 ID。

at -c OLDJOBID | at NEWTIME
atrm OLDJOBID

This will assign the job a new id for its new time.

at -c OLDJOBID | at NEWTIME
atrm OLDJOBID
黯淡〆 2024-10-11 13:43:02

我不确定是否有办法将它们重新安排在不同的时间,但您可以从 at 中完全删除它们,如下所示:

首先列出作业:

$ at -l
9944    2010-11-29 15:00 a dogbane
9945    2010-11-29 15:00 a dogbane

然后删除它们:

$ at -d 9944
$ at -d 9945

然后您可以重新创建它们如果你想。

I'm not sure if there is a way to reschedule them for a different time, but you can remove them completely from at like this:

First list the jobs:

$ at -l
9944    2010-11-29 15:00 a dogbane
9945    2010-11-29 15:00 a dogbane

Then remove them:

$ at -d 9944
$ at -d 9945

You can then recreate them if you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文