Reputation: 304662
Something similar to linux
cat /proc/uptime
which returns the uptime in seconds, and preferably not parsing uptime(1).
Upvotes: 13
Views: 11589
Reputation: 6782
For the benefit of Delphi developers:
First we would declare a function ExecuteCommand which can run a command such as 'sysctl kern.boottime' and get its output.
We would use the libC functions popen, fgets, and 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}
This would return a value such as:
{ sec = 1730143666, usec = 758303 } Mon Oct 28 21:27:46 2024
Now lets declare a function that can extract a named regex group:
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;
And also declare a function that returns a Delphi TDateTime from Unix epoch (number of seconds since 1/1/1970):
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;
And you call it like:
var Output := ExecuteCommand(AnsiString('sysctl -n kern.boottime'));
var Seconds := GetFirstValue(Output, 'sec\s=\s(?<sec>\d+),', 'sec');
var BootTime := TTimestamps.FromUnix(StrToInt64(Seconds));
BootTime holds the TDateTime value of when the OS was booted.
Upvotes: 0
Reputation: 801
To add to @Bleyddyn's answer (since it's 11 years and counting)...
I needed a small utility to print the uptime in seconds, so I took that code and slightly altered it to compile on modern macOS.
You can clone the luckman212/uptime_s
repo and run ./build.sh
to generate your own universal binary that will simply print the uptime in secs.
Upvotes: 1
Reputation: 4573
correct way:
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;
}
also you could use CACurrentMediaTime()
from QuartzCore.framework (which has same code probably) - Available since OS X v10.5 and iOS 2.0
Upvotes: 1
Reputation: 387
Old question, I know, but I needed to do the same thing so I thought I'd post the code I'm using, which I got from 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);
}
Upvotes: 19
Reputation: 1489
If anyone is trying to do this programmatically using sysctl.h
and is expecting a string back like what you see in the command line, the returned value that I get is a 16 byte array, not a string:
sysctlbyname("kern.boottime", value, &size, NULL, 0);
An example for what gets put into value
in hex starting from the [0] index:
a9 af c6 4e 0 0 0 0 0 0 0 0 28 be 92 55
The first 4 bytes (maybe the first 8, won't know until Jan 2012) is the epoch time in little endian byte order.
Upvotes: 2
Reputation: 1463
A simple Lua script to do exactly what you ask for:
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
Upvotes: 0
Reputation: 1
Unfortunately the "sysctl kern.boottime" returns the seconds of the timestamp, not elapsed seconds.. Multiple calls do not increase the second count, but must be seconds from epoc of the boot date itself.
Upvotes: 0
Reputation: 22717
There is a function UpTime
declared in DriverServices.h. I believe this is equivalent to another function mach_absolute_time
. Both seem to be undocumented.
Upvotes: 0
Reputation: 27601
The Uptime article on Wikipedia has an interesting lead:
Using sysctl
There is also a method of using sysctl to call the system's last boot time: $ sysctl kern.boottime kern.boottime: { sec = 1271934886, usec = 667779 } Thu Apr 22 12:14:46 2010
Which references sysctl(8), which references sysctl(3).
Upvotes: 17