This module contains functions for running system commands. The main difference between this module and the standard subprocess is that it is easy to set a timeout and all output is captured even if a timeout occurs. Also it is easier to use.
import sy
status, out, err = sy.cmd.run('find / -name {}', '*.pl', timeout=90)
print out
All commands take a command template, with {} indicating a placeholder, and arguments for substitution. In the example above the command will become: find / -name \*.pl. Note that the \* has been escaped properly. For more information see sy.cmd.format_cmd() and sy.cmd.run().
import sy
out, err = sy.cmd.do('ifconfig xxge0 up')
# Will fail with sy.CommandError:
# Command "ifconfig XXX up" did not exit with status 0:\
# ifconfig: interface XXX does not exist
The function sy.cmd.do() takes the same arguments as sy.cmd.run() but only returns stdout and stderr and raises an exception if command did not exit successfully.
This is convenient since this pattern of programming is encouraged:
def main():
sy.cmd.do('this')
sy.cmd.do('that')
sy.cmd.do('and that')
try:
main()
except Exception, e:
sy.log.exception('Script failed')
sy.util.fail('Script failed: ' + str(e))
This way we now that if any command fails the execution will stop and the error will be logged before exiting.
To loop through the stdout lines of a command you can use sy.cmd.outlines() which takes the same arguments as sy.cmd.do():
import sy
# print the IP of the default route
for mount in sy.cmd.outlines('mount', timeout=5):
if 'nfs' in mount:
print 'Found NFS mount:', mount.strip()
If the systems has any dangling NFS mounts the command would hang and an sy.cmd.CommandTimeoutError would be raised. The exceptions sy.cmd.CommandError and its subclass sy.cmd.CommandTimeoutError contains all the information about why the command failed:
try:
sy.cmd.do('cat /etc/shadow')
except sy.cmd.CommandError, e:
# Descriptive message of the error
str(e) == 'Command "cat /etc/shadow" did not exit with status 0, ...'
# Stderr from the command
e.err == 'cat: /etc/shadow: Permission denied\n'
# Stdout from the command
e.out == ''
# Exit status of the command
e.status == 1
# The command that was run
e.cmd == 'cat /etc/shadow'
synopsis: | Running system commands |
---|
Command failed error
The stdout collected from the command
The stdout collected from the command
The commands exit status
The command that was run
Command failed due to time out. Subclass of CommandError.
The timeout that was exceeded
Execute a command with a timeout and capture output and exit status:
status, out, err = sy.cmd.run('ls -R {}', '/tmp', timeout=15)
Use the convenience function do() if you want to fire off a command and fail if it doesnt return exit status 0.
Parameters: |
|
---|---|
Returns: | exit status from the command, stdout and stderr. On timeout it raises CommandTimeoutError |
Spawn a command and returns stdout and stderr. If the command does not exit with the expect status (default 0) it raises CommandError.
See run() for the other options.
Parameters: |
|
---|---|
Returns: | stdout and stderr as strings |
Spawn a command and return stdout lines. Same arguments as do() expects :returns: stdout as list of lines
Search for the command and return the full path
>>> import sy
>>> sy.cmd.find('ifconfig')
'/usr/sbin/ifconfig'
Searches the directories specifiend in the environment PATH and a couple of default directories.
Parameters: |
|
---|
Format a shell command using safe escapes and argument substitutions:
>>> format_cmd('ls -l {} | grep {} | wc', ['foo 1', 'bar$baz'])
'ls -l foo\\ 1 | grep bar\\$baz | wc'
Usually you don’t need to call this, it is used to format the command by run(), and derived outlines() and do()
Note
You must escape {} in commands or pass it as a argument. These have the same result:
format_cmd('find . -exec ls \{\} \;')
format_cmd('find . -exec ls {} \;', ['{}'])
Taken from iterpipes