OS module¶
The OS module provides access to low-level, operating-system-dependent functionality.
The module can be loaded using the KDB-X module loading function:
os:use`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
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
- cmd is 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)
- opts is a dictionary of options, as explained below, or () or :: to indicate no options
starts a subprocess that executes the command. opts may include the following keys:
- async (boolean): if false or missing, wait for the process to exit, and return a dictionary with status, stdout and stderr. If true, only start the process and return a dictionary containing pid and any pipe handles created.
- stdin (varying type):
- `pass or ::: standard input is passed through from the console. This is the default in sync mode. Note that on Windows, using 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 may 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 additional stdin element in the result dictionary containing the pipe handle. Only usable in async mode.
- stdout and stderr (varying type):
- `pass or ::: 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.
- `str: standard output/error is returned as a single string with platform-dependent line breaks.
- `bin: standard output/error is returned as a byte list.
- In async mode, the format options only apply to the return value of os.proc.wait. In addition, os.proc.start opens a pipe to the respective stream and returns a handle to it in the return dictionary.
- `dup: for stderr only, the standard error is merged into the same handle as standard output instead of going through two separate handles (equivalent to 2>&1 in shell syntax).
- env (dictionary): environment variables, replacing the whole environment (use os.env to get the current environment to modify or append instead)
The return value is a dictionary that may contain the following keys:
- for sync mode:
- status (int): the exit code of the process
- stdout, stderr (byte list, string or string list): if requested, the contents of the respective stream
- for async mode:
- pid (int): process identifier that can be passed into the other proc functions
- stdin, stdout, stderr (int): if specified in the options, a handle to a pipe that can be written to and read from like a regular file handle (see hopen)
When starting a process in async mode, either proc.wait or proc.kill must be called with the pid in the result. Failing to do this may result in the main process hanging on exit or the subprocess hanging around in the background, depending on the platform.
Reading from the handles returned in stdout or stderr will hang if the child process does not print anything on the respective stream. It may not be possible to interrupt the operation other than by forcibly killing the main process.
proc.wait¶
os.proc.wait p
where
- p is a pid from the result of proc.start with the async:1b option
waits until the process exits and returns the same dictionary that proc.start would in sync mode.
proc.kill¶
os.proc.kill p
where
- p is a pid from the result of proc.start with the async:1b option
terminates the process and returns the same dictionary that proc.start would in sync mode.
proc.running¶
os.proc.running p
where
- p is a pid from the result of proc.start with the async:1b option
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, it 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:`dup])]
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, allowing interaction as long as the launched program is written in a way that it 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]"\\\\\n"
9i
q)os.proc.wait p`pid
status| 0i
stdout| ()
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\""