Як заморозити годинник для конкретного завдання?


0

Наприклад,

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

Або просто

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

Очікуваний результат - часові позначки aта bтекст, намальований на зображенні, точно такі ж.

Це можливо?


3
Що ви насправді намагаєтесь зробити? Ви можете використовувати touchпісля факту зміни дат існуючого файлу.
Денніс Вільямсон

Відповіді:


2

В Linux можливо створити спільну бібліотеку, що переосмислює time(), gettimeofday()і clock_gettime()використовувати статичні значення, а також додати бібліотеку $LD_PRELOAD, яка б обдурила багато програм.

Оновлення: хтось реалізував це як datefudge.


Я пограю по всьому оточенню LD_PRELOAD, дякую!
Xiè Jìléi

5

Оскільки мені довелося реалізувати рішення @ grawity, я думаю, що було б непогано поділитися ним тут:

#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;
}

Тест:

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

2

Ви не можете зупинити системний годинник. Однак ви можете зробити це:

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

1

Ви можете зробити touch a b. Ви також можете зробити touch a; touch --reference=a b.


Дякую. Завдання може включати в себе інші речі, а потім створювати файли, я змінив приклад, щоб це відобразити.
Xiè Jìléi

1

Є проект під назвою faketime, який робить це для вас. Він використовує LD_PRELOAD, і він використовує абсолютний / відносний час.

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).

Ця відповідь призначена для подальших посилань, оскільки у вас вже є робоче рішення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.