summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorThomas Mangin <thomas.mangin@exa.net.uk>2020-04-05 14:02:49 +0100
committerThomas Mangin <thomas.mangin@exa.net.uk>2020-04-06 20:22:35 +0100
commit356950579c2b155f9d41c04ed63c7efde561b43a (patch)
treedc5fe36bf61ce25d85aaac7994545385b0bc6bff /python
parente0f13b79a669e7fc8cadac8757b2f5fbbf51dc99 (diff)
downloadvyos-1x-356950579c2b155f9d41c04ed63c7efde561b43a.tar.gz
vyos-1x-356950579c2b155f9d41c04ed63c7efde561b43a.zip
util: T2226: improve popen, cmd and add run
improves open and cmd adds a new help function run. the extra optional arguments provide all the features of subprocess used by every module of VyOS. popen matches closely subprocess.Popen cmd matches closely subprocess.check_output run matches closely subprocess.call and os.system popen returns the string and errord code cmd returns the string and raise on error (the class can be defined the default is OSError) run returns the return code of the command the options are: shell=None, the code auto-detect is a shell is required decode=None, use .decode() otherwise the encoding will be used env=None, universal_newlines=None: as per subprocess.Popen input=None, timeout=None, stdout=PIPE, stderr=STDOUT, as per Popen.communicate
Diffstat (limited to 'python')
-rw-r--r--python/vyos/util.py67
1 files changed, 52 insertions, 15 deletions
diff --git a/python/vyos/util.py b/python/vyos/util.py
index c8ab43c11..f63ed057e 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -16,7 +16,7 @@
import os
import re
import sys
-from subprocess import Popen, PIPE, STDOUT
+from subprocess import Popen, PIPE, STDOUT, DEVNULL
# debugging
@@ -33,29 +33,63 @@ def debug_msg(message, section=''):
# commands
-
-def popen(command, section=''):
- p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True)
- tmp = p.communicate()[0].strip()
+# popen does not raise
+# it returns the output of the command and the error code
+def popen(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None):
+ use_shell = shell
+ if shell is None:
+ use_shell = True if ' ' in command else False
+ p = Popen(
+ command,
+ stdout=stdout, stderr=stderr,
+ env=env, shell=use_shell,
+ universal_newlines=universal_newlines,
+ )
+ tmp = p.communicate(input, timeout)[0].strip()
debug_msg(f"cmd '{command}'", section)
- decoded = tmp.decode()
+ decoded = tmp.decode(decode) if decode else tmp.decode()
if decoded:
debug_msg(f"returned:\n{decoded}", section)
return decoded, p.returncode
-
-def cmd(command, section=''):
- decoded, code = popen(command, section)
+# run does not raise
+# it returns the error code
+def run(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None):
+ _, code = popen(
+ command, section,
+ stdout=stdout, stderr=stderr,
+ input=input, timeout=timeout,
+ env=env, shell=shell,
+ universal_newlines=universal_newlines,
+ decode=decode,
+ )
+ return code
+
+# cmd does raise
+# it returns the output
+def cmd(command, section='', shell=None, input=None, timeout=None, env=None, universal_newlines=None, stdout=PIPE, stderr=STDOUT, decode=None, raising=None, message=''):
+ decoded, code = popen(
+ command, section,
+ stdout=stdout, stderr=stderr,
+ input=input, timeout=timeout,
+ env=env, shell=shell,
+ universal_newlines=universal_newlines,
+ decode=decode,
+ )
if code != 0:
- # error code can be recovered with .errno
- raise OSError(code, f'{command}\nreturned: {decoded}')
+ feedback = message + '\n' if message else ''
+ feedback += f'failed to run command: {command}\n'
+ feedback += f'returned: {decoded}\n'
+ feedback += f'exit code: {code}'
+ if raising is None:
+ # error code can be recovered with .errno
+ raise OSError(code, feedback)
+ else:
+ raise raising(feedback)
return decoded
-# file manipulation
-
-
-
+# This is now deprecated
def subprocess_cmd(command):
""" execute arbitrary command via Popen """
from subprocess import Popen, PIPE
@@ -63,6 +97,9 @@ def subprocess_cmd(command):
p.communicate()
+# file manipulation
+
+
def read_file(path):
""" Read a file to string """
with open(path, 'r') as f: