类似于linux的东西
cat /proc/uptime
返回以秒为单位的正常运行时间,并且最好不解析正常运行时间(1)。
老问题,我知道,但我需要做同样的事情,所以我想我应该发布我正在使用的代码,这是我从 http://cocoadev.com/wiki/FindingUptime
获得的#include <time.h>
#include <errno.h>
#include <sys/sysctl.h>
double uptime()
{
struct timeval boottime;
size_t len = sizeof(boottime);
int mib[2] = { CTL_KERN, KERN_BOOTTIME };
if( sysctl(mib, 2, &boottime, &len, NULL, 0) < 0 )
{
return -1.0;
}
time_t bsec = boottime.tv_sec, csec = time(NULL);
return difftime(csec, bsec);
}
如果有人尝试使用
sysctl.h
以编程方式执行此操作,并且期望返回一个像命令行中所看到的字符串,那么我得到的返回值是一个 16 字节数组,而不是字符串:
sysctlbyname("kern.boottime", value, &size, NULL, 0);
从 [0] 索引开始以十六进制形式放入
value
的示例:
a9 af c6 4e 0 0 0 0 0 0 0 0 28 为 92 55
前 4 个字节(可能是前 8 个,直到 2012 年 1 月才知道)是小端字节顺序的纪元时间。
正确做法:
CFTimeInterval getSystemUptime(void)
{
enum { NANOSECONDS_IN_SEC = 1000 * 1000 * 1000 };
static double multiply = 0;
if (multiply == 0)
{
mach_timebase_info_data_t s_timebase_info;
kern_return_t result = mach_timebase_info(&s_timebase_info);
assert(result == noErr);
// multiply to get value in the nano seconds
multiply = (double)s_timebase_info.numer / (double)s_timebase_info.denom;
// multiply to get value in the seconds
multiply /= NANOSECONDS_IN_SEC;
}
return mach_absolute_time() * multiply;
}
您也可以使用 QuartzCore.framework 中的
CACurrentMediaTime()
(可能具有相同的代码) - 自 OS X v10.5 和 iOS 2.0 起可用
添加@Bleyddyn的答案(因为已经11年了并且还在继续)...
我需要一个小实用程序来在几秒钟内打印正常运行时间,因此我对该代码进行了稍微修改以在现代 macOS 上进行编译。
luckman212/uptime_s
存储库并运行 ./build.sh
来生成您自己的通用二进制文件,该二进制文件将简单地以秒为单位打印正常运行时间。
DriverServices.h 中声明了一个函数
UpTime
。 我相信这相当于另一个函数mach_absolute_time
。 两者似乎都没有记录。
不幸的是,“sysctl kern.boottime”返回时间戳的秒数,而不是经过的秒数。多次调用不会增加秒计数,但必须是从启动日期本身的 epoc 算起的秒数。
一个简单的 Lua 脚本可以完全满足您的要求:
local now=tonumber(io.popen("date +%s"):read())
local boottime=tonumber(io.popen("sysctl -n kern.boottime"):read():match("sec = (%d+)"))
local uptime=now-boottime
为了Delphi开发者的利益:
首先我们声明一个函数 ExecuteCommand,它可以运行“sysctl kern.boottime”等命令并获取其输出。
我们将使用 libC 函数 popen、fgets 和 pclose
const libc = '/usr/lib/libc.dylib';
/// Man Page: http://man7.org/linux/man-pages/man3/popen.3.html
function popen(const command: MarshaledAString; const _type: MarshaledAString): TStreamHandle; cdecl; external libc name _PU + 'popen';
/// Man Page: http://man7.org/linux/man-pages/man3/pclose.3p.html
function pclose(filehandle: TStreamHandle): Int32; cdecl; external libc name _PU + 'pclose';
/// Man Page: http://man7.org/linux/man-pages/man3/fgets.3p.html
function fgets(Buffer: Pointer; Size: Int32; Stream: TStreamHAndle): Pointer; cdecl; external libc name _PU + 'fgets';
/// Utility function to return a buffer of ASCII-Z data as a string.
function BufferToString(Buffer: Pointer; MaxSize: UInt32): string;
var
Cursor: ^UInt8;
EndOfBuffer: NativeUInt;
begin
Result := EmptyStr;
if not Assigned(Buffer) then
Exit;
Cursor := Buffer;
EndOfBuffer := NativeUint(Cursor) + MaxSize;
while (NativeUint(Cursor) < EndOfBuffer) and (Cursor^ <> 0) do
begin
Result := Result + Chr(Cursor^);
Cursor := Pointer(Succ(NativeUInt(Cursor)));
end;
end;
{$if defined(POSIX)}
// URL https://chapmanworld.com/calling-linux-commands-from-delphi/
function ExecuteCommand(const CommandLine: AnsiString): string;
var
Handle: TStreamHandle;
Data: array[0..511] of UInt8;
begin
Handle := popen(PAnsiChar(CommandLine), 'r');
try
Result := EmptyStr;
while fgets(@data[0], Sizeof(Data), Handle) <> nil do
Result := Result + BufferToString(@Data[0], SizeOf(Data));
finally
pclose(Handle);
end;
end;
{$endif}
这将返回一个值,例如:
{ sec = 1730143666, usec = 758303 } Mon Oct 28 21:27:46 2024
现在让我们声明一个可以提取命名正则表达式组的函数:
function GetFirstValue(const Text, Mask, GroupName: string): string;
begin
Result := EmptyStr;
var MC := TRegex.Matches(Text, Mask, [TRegexOption.roIgnoreCase, TRegexOption.roMultiLine, TRegexOption.roCompiled, TRegexOption.roExplicitCapture]);
var M := Default(TMatch);
for M in MC do
begin
Result := M.Groups[GroupName].Value;
Break;
end;
end;
并且还声明一个从 Unix 纪元返回 Delphi TDateTime 的函数(自 1970 年 1 月 1 日以来的秒数):
function FromUnix(const Value: Int64): TDateTime;
// Sets UnixStartDate to TDateTime of 01/01/1970
const UnixStartDate: TDateTime = 25569.0; // EncodeDate(1970, 1, 1)
begin
Result := (Value / 86400) + UnixStartDate;
end;
你这样称呼它:
var Output := ExecuteCommand(AnsiString('sysctl -n kern.boottime'));
var Seconds := TRegexInternal.GetFirstValue(Output, 'sec\s=\s(?<sec>\d+),', 'sec');
var BootTime := TTimestamps.FromUnix(StrToInt64(Seconds));
BootTime 保存操作系统启动时的 TDateTime 值。