Changing what time a process thinks it is with libfaketime

5593

Author: Ben Martin

With libfaketime you can tell a process that the current time is something different from the machine’s system clock. This fake time setting affects not only the functions directly related to reading the system time, but also file timestamps such as modification times. With libfaketime you can test how a program will respond when it is running in the future or in a different timezone without having to change your machine’s system clock. Timezone testing can be useful for network applications where a certificate may have already expired in a given timezone but might still work in your local environment.

libfaketime works as a preload library. When you want to use it, you set the LD_PRELOAD environment variable to include the shared library when you execute a program. For example, when running the date program with LD_PRELOAD set, the machine’s dynamic linker will load the libfaketime library into the new process, and by loading libfaketime, certain functions will be mapped into the libfaketime library instead of using your system functions directly. libfaketime cannot be used with statically linked or setuid programs, because LD_PRELOAD is not available to such programs.

You can set the fake time to be a relative offset (such as 12 hours ago) or an absolute value, or to start at an absolute value. libfaketime uses the FAKETIME environment variable to work out how you want to change the system time. By default, libfaketime also changes file timestamps reported by the system to take your FAKETIME modification into account. If you do not want file timestamps to be changes as well, set the environment variable NO_FAKE_STAT=1.

Version 0.5 of libfaketime is available as a 1-Click install for openSUSE 10.3. There are no packages of libfaketime for Fedora or Ubuntu. You can build from source as shown below:

$ tar xzvf /.../libfaketime-0.8.tar.gz $ cd ./libfaketime* $ make $ sudo make install

The above commands install the faketime program along with its manual page and the libfaketime shared library. Using faketime lets you avoid having to insert library paths into environment variables in order to use libfaketime. The faketime program takes some optional flags, a timestamp, and then the name and arguments of the program you wish to run with the modified time settings. This invocation style follows the pattern of applications like time(1) and nice(1), so you can use an existing command-line invocation by simply adding faketime and its arguments as a prefix to another command, as shown below, where I execute the date command with a fake clock that is 10 minutes in the past:

$ date Sat Sep 6 15:01:44 EST 2008 $ faketime -f '-10m' date Sat Sep 6 14:51:45 EST 2008

Setting the time to an absolute value has the drawback that the time reported to the application will never change. One upshot of absolute time setting is that you can use a file’s timestamp to set the fake time value. In the below code block I first create a reference file with a timestamp of February 1999. To use a file’s timestamp as an absolute value with libfaketime, you must export the FAKETIME_FMT environment variable to tell libfaketime that you are passing in the number of seconds since the Epoch as the fake time value. You can then either use the faketime program to run your application with this modified time, or directly set up libfaketime using environment variables as shown in the third block of commands below:

$ touch -t 199902202359 party $ ls -lt party -rw-rw-r-- 1 ben ben 0 1999-02-20 23:59 party $ stat -c %Y /tmp/party 919519140 $ export FAKETIME_FMT=%s $ faketime -f `stat -c %Y /tmp/party` date Sat Feb 20 23:59:00 EST 1999 $ export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 $ export FAKETIME=`stat -c %Y /tmp/party` $ export FAKETIME_FMT=%s $ date Sat Feb 20 23:59:00 EST 1999

You can also specify the absolute time that you would like the clock to start ticking from. The below example should make this clearer. First I use the %y option to the stat command to report the time in a format that is usable for a faketime start at timestamp. I specify that I am passing a “start at” timestamp by prepending an @ symbol to the time value. When I preload the libfaketime library, the system clock is reported as the timestamp of the file as above. However, the small example program that gets the system time, waits two seconds, and then obtains the system time again works differently when using a “start at” time. As the output shows, the time has advanced two seconds. If you use an absolute time with libfaketime (as was done in the above example) then running ./timetest twice would report the same time twice.

$ export FAKETIME="@`stat -c %y /tmp/party`" $ export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 $ date Sat Feb 20 23:59:00 EST 1999 $ cat timetest.cpp #include <iostream> using namespace std; int main( int, char** ) { time_t tt = 0; time( &tt ); cout << tt << endl; sleep(2); time( &tt ); cout << tt << endl; return 0; } $ g++ timetest.cpp -o timetest $ ./timetest 919519140 919519142

The third way you can tell libfaketime the fake time you want is by specifying a relative offset you would like applied to the current system clock. You can use the single character postfixes m(inutes), h(ours), d(ays), and y(ears) to specify the units of your offset. The default is an offset in seconds. Use either the minus or plus prefix to specify that you want the offset to be subtracted from or added to the current system time.

You can also specify the value from the FAKETIME environment variable in the ~/.faketimerc file if you want to set a default fake time. I couldn’t find a way to use the ~/.faketimerc with the faketime program, but it works well if you export the LD_PRELOAD environment variable as shown below:

$ date Sat Sep 6 15:39:58 EST 2008 $ echo '+15m' >| ~/.faketimerc $ export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 $ date Sat Sep 6 15:55:00 EST 2008

One final feature of note is the ability to run the fake clock at a different speed than real time. For example, the below invocation of the timetest program shown above runs the fake clock twice as fast as it should normally run. The rate is specified in the x2 parameter. You can also specify a decimal value like x0.5 to slow down the fake clock. Because I am running the fake clock at twice real time speed, the second time value obtained by timetest after a two-second sleep is actually four seconds later.

$ faketime -f '+2d x2' ./timetest 1220853830 1220853834

libfaketime allows you to change how a single program will see your system clock without your needing to modify the system time. This is convenient when you want to see how a network application will look in another timezone or you want to test how an application will work in the future. The ability to change how fast the fake time progresses is a wonderful feature for testing how well an application that has some time-dependent logic in it will work on hardware that is substantially faster or slower than that which you are using to perform the testing.

Category:

  • Tools & Utilities