Como congelar o relógio para uma tarefa específica?

0

Por exemplo,

# clock-pause
# touch a
# touch b
# convert -draw 'date' text_draw.gif
# clock-resume

Ou simplesmente

# freeze-exec sh -c 'touch a; touch b; convert -draw 'date' text_draw.gif'

O resultado esperado é o registro de data e hora de a e b , e o texto desenhado para a imagem é exatamente o mesmo.

É possível?

    
por Xiè Jìléi 27.12.2010 / 07:12

5 respostas

2

No Linux, talvez seja possível escrever uma biblioteca compartilhada que substitua time() , gettimeofday() e clock_gettime() para usar valores estáticos e adicione a biblioteca a $LD_PRELOAD , o que enganaria muitos programas. / p>

Atualização: alguém implementou isso como datefudge .

    
por 27.12.2010 / 16:29
5

Desde que eu tive que implementar a solução do @growity, eu acho que seria legal compartilhá-lo aqui:

#define _GNU_SOURCE
#include <sys/types.h>
#include <dlfcn.h>
#include <stddef.h>

/* Frozen time (usual time_t, from UNIX epoch) */
const time_t fixedTime=652789800;

/* Deprecated, thus it seems not to be present in sys/types.h */
struct timezone
{
   int tz_minuteswest;     /* minutes west of Greenwich */
   int tz_dsttime;         /* type of DST correction */
};

/* Typedef for the function ptr to the original gettimeofday */
typedef int (*gettimeofday_t)(struct timeval *tv, struct timezone *tz);

/* original gettimeofday */
gettimeofday_t gettimeofday_orig = NULL;

time_t time(time_t * t)
{
    if(t!=NULL)
        *t=fixedTime;
    return fixedTime;
}

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
    if(tz!=NULL)
    {
        /* forward requests about tz to the original gettimeofday */
        if(gettimeofday_orig==NULL)
        {
            gettimeofday_orig=(gettimeofday_t) dlsym(RTLD_NEXT, "gettimeofday");
            if(gettimeofday_orig==NULL)
                return -1;
        }
        int ret=gettimeofday_orig(NULL, tz);
        if(!ret)
            return ret;
    }
    if(tv!=NULL)
    {
        tv->tv_sec=fixedTime;
        tv->tv_usec=0;
    }
    return 0;
}

int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
    (void)clk_id;
    if(tp!=NULL)
    {
        tp->tv_sec=fixedTime;
        tp->tv_nsec=0;
    }
    return 0;
}

Teste:

matteo@teoxubuntu:~/cpp/detourtest$ gcc -O3 -fPIC -Wall -Wextra -shared timedetour.c -o libtimedetour.so
matteo@teoxubuntu:~/cpp/detourtest$ LD_PRELOAD=/home/matteo/cpp/detourtest/libtimedetour.so date
sab  8 set 1990, 12.30.00, CEST
    
por 21.12.2011 / 01:14
2

Você não pode parar o relógio do sistema. No entanto, você pode fazer isso:

now=$(date +%s.%N)
# $now now contains a Unix timestamp at nanosecond precision
touch -d @$now a b c
convert -draw "$(date -d @$now)" text_draw.gif
    
por 27.12.2010 / 16:11
1

Você pode fazer touch a b . Você também pode fazer touch a; touch --reference=a b .

    
por 27.12.2010 / 09:15
1

Existe um projeto chamado faketime que faz isso para você. Usa o LD_PRELOAD e usa tempos absolutos / relativos.

libfaketime intercepts various system calls which programs use to
retrieve the current date and time. It can then report faked dates and times
(as specified by you, the user) to these programs. This means you can modify
the system time a program sees without having to change the time system-wide.

libfaketime allows you to specify both absolute dates (e.g., 01/01/2004) and
relative dates (e.g., 10 days ago).

Esta resposta é para referências futuras, pois você já tem uma solução de trabalho.

    
por 26.11.2013 / 08:36