2010-11-29 17 views
5

¿Hay alguna forma de cambiar la fecha de un trabajo que se haya emitido con el comando unix at?Reprogramar un trabajo at

Necesito hacer esto porque mi aplicación ha programado demasiados trabajos al mismo tiempo, lo que hará que la máquina se detenga por completo.

Respuesta

9

Esta es probablemente depende de la implementación, pero en mi sistema que puede cambiar el nombre del trabajo, así:

$ # 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 

Los últimos 8 dígitos hexadecimales en el nombre del archivo es el número de minutos de la Época Unix que determina el momento para ejecutar el trabajo. Incremente eso por el número de minutos para retrasar.

Editar:

A continuación se muestra una secuencia de comandos Bash para automatizar los pasos anteriores. Aquí hay algunas carreras ejemplo:

Crear un trabajo:

$ 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 

volver a programar el trabajo durante una hora más tarde:

$ 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 

reprogramarla durante 15 minutos más temprano:

$ 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 

Ahora agregue un día:

$ 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 

Puede especificar una cola:

$ sudo atrs -q b 141 120 

hacer un simulacro:

$ 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 

Aquí está la secuencia de comandos:

#!/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 
+0

Un poco hackish pero en realidad funciona. Eso realmente fue un salvavidas. ¡Rock! –

+1

@Michael: Sí, supongo que sí, aunque en primer lugar es donde se almacena el programa en el nombre del archivo. Edité mi respuesta y agregué un script que automatiza los pasos que describí en mi respuesta original. –

+0

¡Gracias por el guión de shell! ¡Trabajado como un encanto! +1 –

1

no estoy seguro de si hay una manera de reprogramar ellos por un tiempo diferente, pero puede eliminarlos por completo de at así:

Primera lista de los puestos de trabajo:

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

Entonces eliminarlos:

$ at -d 9944 
$ at -d 9945 

A continuación, puede volver a crearlos si lo desea.

3

Esto asignará el trabajo de una nueva identificación para su nuevo tiempo

at -c OLDJOBID | at NEWTIME 
atrm OLDJOBID 
+0

Eso hace que las cosas de la envoltura se dupliquen. –

+0

@Dennis Sí, lo hace.Pero debería ser lo mismo, no pensé que realmente hiciera tanta diferencia que las cosas de la envoltura estuvieran duplicadas. (Si no es el mismo material de envoltura, entonces las cosas del envoltorio del trabajo anterior vienen en segundo lugar, así que eso es lo que se usa). –

Cuestiones relacionadas