3.5 KiB
os
Luna runs scripts in a sandbox, so the standard os table is trimmed to its
safe, time-related functions — os.time, os.clock, os.date,
os.difftime — while the parts that touch the system
(os.execute, os.getenv, os.remove, os.exit, …) are removed. To that
trimmed table Luna adds a high-resolution clock, an async sleep, and access to
the script's command-line arguments.
local t0 = os.microtime()
os.sleep(0.25)
print(string.format("waited %.3fs", os.microtime() - t0)) --> waited ~0.250s
os.microtime()
Return the current time as a Unix timestamp in seconds, as a float with
sub-second precision — unlike os.time, which is whole seconds only. It is the
right tool for measuring elapsed time:
local start = os.microtime()
doSomeWork()
local elapsed = os.microtime() - start
log.info(string.format("took %.1f ms", elapsed * 1000))
It reads the system wall clock, so it tracks real time (and can jump if the clock is adjusted); for interval timing the difference of two readings is what you want.
os.args()
Return the command-line arguments passed to the script, as an array (a fresh
table on every call, so it is safe to mutate). On the luna command line the
script's arguments are everything after the script path — even a token spelled
like a luna flag goes to the script there, so luna's own flags (--sandbox &
co.) must come before the path. A -- between the path and the arguments is
accepted and skipped:
luna script.lua one two --three
luna --sandbox script.lua -- one two --three
-- script.lua
for i, arg in ipairs(os.args()) do
print(i, arg) --> 1 one / 2 two / 3 --three
end
An executable script with a #!/usr/bin/env luna shebang line receives its
arguments the same way, with no -- needed:
./script.lua one two --three
In the REPL os.args() returns an empty table. Arguments are passed through
as raw byte strings, without UTF-8 conversion.
os.sleep(seconds)
Pause for seconds (a float, so os.sleep(0.1) is 100 ms). This is an async
sleep: it suspends the script on the runtime instead of blocking the OS thread,
so concurrent work keeps running while it waits.
os.sleep(1) -- one second
os.sleep(0.05) -- 50 milliseconds
seconds must be a non-negative finite number.
Because the sleep suspends rather than blocks, sibling tasks started with
task.join make progress during the wait — that is what lets
several sleeps (or requests, or queries) overlap:
-- finishes in ~0.3s, not 0.6s — the sleeps overlap
task.join(
function() os.sleep(0.3) end,
function() os.sleep(0.2) end,
function() os.sleep(0.1) end
)
One caveat applies to coroutines you drive yourself with coroutine.wrap /
coroutine.resume: there, os.sleep does not actually wait. See
Self-driven coroutines for the full
explanation — the rule is to run anything that needs to sleep through
task.join.
Notes
- The sandbox keeps the time functions.
os.time,os.clock,os.date, andos.difftimework as in stock Lua; functions that touch the system are not present. microtimefor durations,timefor timestamps. Useos.microtimewhen you need sub-second precision or are timing an interval;os.timewhen whole seconds suffice.sleepis cooperative. It yields to the runtime, so it is cheap to sleep inside concurrent tasks — see Concurrency.