OS module¶
The OS module provides access to low-level, operating-system-dependent functionality.
Load the module with the KDB-X module loading function:
os:use`kx.os
read¶
Read raw data from a file or handle
os.read[f;o;n]
os.read[h;o;n]
where
fis a file symbolhis a file handle opened by hopenoandnare non-negative integers
returns binary data from the source starting at offset o and reading up to n bytes, ignoring kdb+ file compression (files are transparently decompressed by read1).
q)(`:f;16;1;0)set `time$til 1000
`:f
q)`char$os.read[`:f;0;8]
"kxzipped"
q)h:hopen`:f
q)`char$os.read[h;0;8]
"kxzipped"
q)hclose h
sleep¶
Suspend the process for a given duration
os.sleep i
os.sleep t
where
iis a short, int or long indicating a number of millisecondstis a timespan, time or second indicating a time period
suspends the process for the given time period.
q)\t os.sleep 300
300
q)\t os.sleep 00:00:10
10000
q)\t os.sleep 0D00:00:00.01
10
env¶
Get environment
os.env[]
returns the current environment variables as a dictionary.
q)os.env[]
QHOME | "/home/user/kdb"
SHELL | "/bin/bash"
PWD | "/home/user/kdbx"
proc¶
Interact with subprocesses
proc.start¶
os.proc.start[cmd;opts]
where
cmdis a string containing a command or a string list containing the program name and its parameters (parameters with embedded spaces, backslashes, or quotes are only allowed in a string list)optsis a dictionary of options, as explained below, or()or::to indicate no options
starts a subprocess that runs the command. opts can include the following keys:
async(boolean): if false or missing, wait for the process to exit, and return a dictionary withstatus,stdoutandstderr. If true, only start the process and return a dictionary containingpidand any pipe handles created.stdin(varying type):`pass: standard input is passed through from the console. This is the default in sync mode. Note that on Windows, if you use this option when the function is called from a source other than console input (e.g. from an IPC handle), the first line of input can still be sent to the parent process instead of subprocess.`discard: standard input is redirected from the null device.- a string or list of strings: the content is piped into the process and then the standard input handle is closed. In async mode, the default is equivalent to using this option with an empty string.
`pipe: open a pipe and return an additionalstdinelement in the result dictionary containing the pipe handle. Only usable in async mode.
stdoutandstderr(varying type):`pass: standard output/error is passed through to the console. This is the default.`discard: standard output/error is redirected to the null device.`text: standard output/error is returned as a list of strings (similar toread0).`bin: standard output/error is returned as a byte list (similar toread1).`stdout: forstderronly, the standard error is merged into the same handle as standard output instead of going through two separate handles (equivalent to2>&1in shell syntax).
env(dictionary): environment variables, replacing the whole environment (use theos.envfunction to get the current environment to modify or append instead)
Note that in async mode, the text and bin options apply to the return value of os.proc.wait and os.proc.kill.
The return value is a dictionary that can contain the following keys:
- for sync mode:
status(int): the exit code of the processstdout,stderr(byte list or string list): if requested, the contents of the respective stream
- for async mode:
pid(int): process identifier that can be passed into the otherprocfunctionsstdin,stdout,stderr(int): if specified in the options, a handle to a pipe that can be written to or read from like a regular file handle (see hopen)
When you start a process in async mode, call proc.wait or proc.kill with the pid in the result. Otherwise the main process can hang on exit, or the subprocess can keep running in the background, depending on the platform.
Reading from the handles returned in stdout or stderr hangs if the child process doesn't print anything on the respective stream. You can interrupt the operation only by forcibly killing the main process.
proc.wait¶
os.proc.wait p
where
pis apidfrom the result ofproc.startwith theasync:1boption
waits until the process exits and returns the same dictionary that proc.start would in sync mode.
proc.kill¶
os.proc.kill p
where
pis apidfrom the result ofproc.startwith theasync:1boption
terminates the process and returns the same dictionary that proc.start would in sync mode.
proc.running¶
os.proc.running p
where
pis apidfrom the result ofproc.startwith theasync:1boption
returns a boolean indicating whether the process is still running (Windows only; on Linux this is always 1b). Always returns 0b if it has already been reclaimed using proc.wait or proc.kill.
Examples¶
In its simplest form, os.proc.start can act as a substitute for system:
q)os.proc.start["sort";::]
ccc
bbb
aaa
^D
aaa
bbb
ccc
status| 0
Standard input can be passed in programmatically:
q)os.proc.start["sort";([stdin:("bbb";"ccc";"aaa")])]
aaa
bbb
ccc
status| 0
Standard output and error can be captured separately:
q)os.proc.start["ls /bin/bash /bin/foo";([stdout:`text;stderr:`text])]
status| 2i
stdout| ,"/bin/bash"
stderr| ,"ls: cannot access '/bin/foo': No such file or directory"
Or the two streams can be merged:
q)os.proc.start["ls /bin/bash /bin/foo";([stdout:`text;stderr:`stdout])]
status| 2i
stdout| ("ls: cannot access '/bin/foo': No such file or directory";"/bin/bash")
Async mode allows the parent process to continue executing other code while the subprocess runs in the background:
q)os.proc.start["du -h --max-depth=1 /home";([async:1b;stdout:`text;stderr:`text])]
pid | 7276
stdout| 4
stderr| 6
// ... perform other tasks while du runs in the background
q)os.proc.wait 7276i
status| 0i
stdout| ("57G\t/home/user";"57G\t/home")
stderr| ()
Standard input can be sent via a pipe. This allows interaction if the launched program can print output before it finishes reading all of its input:
q)show p:os.proc.start["q";([async:1b;stdin:`pipe;stdout:`text;stderr:`discard])]
pid | 2971
stdin | 9
stdout| 10
q)p[`stdin]"\\p 0W\n"
9i
q)p[`stdin]"\\p\n"
9i
q)show childPort:read0 p`stdout
"35473i"
//childPort now can be used to open an IPC handle for more robust interaction
q)p[`stdin]"exit 0\n"
9i
q)os.proc.wait p`pid
status| 0i
stdout| ()
Note
When using the stdin option with a q process, you may need to set the environment variable KX_TTY=1 to ensure that it does not quit
in a non-interactive environment.
Environment variables can be passed in:
q)show p:os.proc.start["q";([async:1b;stdin:`pipe;stdout:`text;stderr:`discard;env:os.env[],([TEST_AAAA:"aaaa"])])]
pid | 16394
stdin | 9
stdout| 10
q)p[`stdin]"getenv`TEST_AAAA\n"
9i
q)os.proc.wait p`pid
status| 0i
stdout| ,"\"aaaa\""