我希望我的 go 程序在 ubuntu 服务器(14.04)上运行,并由主管守护,以使用假服务器时间。
在我的主管配置中,我使用它作为执行命令:
"faketime 'last Friday 5 pm' /home/user/main"
程序运行,但显示当前时间。
根据这篇文章: 使用 libfaketime 更改进程认为的时间
libfaketime 不能与静态链接或 setuid 程序一起使用,因为 LD_PRELOAD 不适用于此类程序。
有没有办法让我编译的go程序使用faketime?
问题是
faketime
使用LD_PRELOAD
环境变量来指示程序的动态加载器在启动时加载libfaketime
。 libfaketime
将执行所谓的“插入”操作 - 用其自己的例程副本替换正常的动态库例程 - 这样,当将来进行动态库调用时,libfaketime
可以影响发生的情况。特别是,libfaketime
插入了与时间相关的调用,因此它能够向程序返回假值。
这适用于大多数程序的原因是它们使用
libc
进行系统调用。 libc
提供了与系统调用交互的高级函数,使系统编程变得更容易。在大多数使用 libc
的语言中,二进制文件是动态链接的,这意味着 libc
实际上并不包含在二进制文件中,而是预计 libc
的编译版本(称为“目标文件”)将包含在二进制文件中。当二进制文件运行时,动态库就存在于系统中,此时可以加载动态库。这种动态加载使得通过 faketime
指令实现 LD_PRELOAD
成为可能,这改变了加载器的行为。
然而,Go 有两点不同。首先,它是静态链接的,因此没有加载程序可以关注
LD_PRELOAD
。其次,它不使用 libc
,所以即使它是动态链接的,并且 LD_PRELOAD
技巧起作用了,libc
也永远不会被调用,所以它实际上仍然无法实现欺骗的预期目标编程使用假时间函数。
https://github.com/harkaitz/go-faketime 可以用于此目的。
import "github.com/harkaitz/go-faketime"
ftime.now() //reads the time set for faketime
在内部检查环境变量
LD_PRELOAD
是否包含字符串libfaketime
// code snippet from https://github.com/harkaitz/go-faketime/blob/master/faketime.go
if strings.Index(os.Getenv("LD_PRELOAD"), "libfaketime") == -1 {
return time.Now()
}
cmd = exec.Command("date", "+%s")
stdout, err = cmd.Output()
我希望这有帮助!