0

Code:

# cat mylinux.py
# This program is to interact with Linux

import os

v = os.system("cat /etc/redhat-release")

Output:

# python mylinux.py
Red Hat Enterprise Linux Server release 7.6 (Maipo)

In the above output, the command output is displayed regardless of the variable I defined to store the output.

How to store the shell command output to a variable using os.system method only?

Sachin Aravind
  • 150
  • 1
  • 2
  • 11
  • 1
    Why `os.system` only? To cite the documentation of `os.system`: "The `subprocess` module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function." – Matthias Apr 27 '22 at 07:42
  • 1
    As @Mattias points out, `os.system()` has been deprecated for decades. One of the many reasons why is because it does not do what you want. Insisting on a legacy function that doesn't do what you want, just because you don't want to learn about how to do properly, is not a good strategy for success. – BoarGules Apr 27 '22 at 07:51
  • os.sysetm is simple to use. Can you confirm if there are any ways to store the shell command output to a variable by using os module? – Sachin Aravind Apr 27 '22 at 07:51
  • Let me get this right: You insist in using a possibly more complicated and less reliable way to get the output, just because you don't want to read "[Replacing Older Functions with the subprocess Module](https://docs.python.org/3/library/subprocess.html#subprocess-replacements)"? – Matthias Apr 27 '22 at 07:55
  • My intention is to use Python as an interpreter to communicate with your OS and execute any command you wish to run. If I want to use subprocess, I would need to split all such commands. That would make it more complicated. – Sachin Aravind Apr 27 '22 at 08:01
  • May be you can use `os.popen`, but that's just a wild guess. See https://stackoverflow.com/questions/3503879/assign-output-of-os-system-to-a-variable-and-prevent-it-from-being-displayed-on for more info. – Matthias Apr 27 '22 at 08:19

1 Answers1

2

By using module subprocess. It is included in Python's standard library and aims to be the substitute of os.system. (Note that the parameter capture_output of subprocess.run was introduced in Python 3.7)

>>> import subprocess
>>> subprocess.run(['cat', '/etc/hostname'], capture_output=True)
CompletedProcess(args=['cat', '/etc/hostname'], returncode=0, stdout='example.com\n', stderr=b'')
>>> subprocess.run(['cat', '/etc/hostname'], capture_output=True).stdout.decode()
'example.com\n'

In your case, just:

import subprocess

v = subprocess.run(['cat', '/etc/redhat-release'], capture_output=True).stdout.decode()

Update: you can split the shell command easily with shlex.split provided by the standard library.

>>> import shlex
>>> shlex.split('cat /etc/redhat-release')
['cat', '/etc/redhat-release']
>>> subprocess.run(shlex.split('cat /etc/hostname'), capture_output=True).stdout.decode()
'example.com\n'

Update 2: os.popen mentioned by @Matthias

However, is is impossible for this function to separate stdout and stderr.

import os

v = os.popen('cat /etc/redhat-release').read()
Xinhe Wang
  • 145
  • 2
  • 9
  • This is bit complex. I am looking for a simpler step. I prefer to use os module instead of subprocess where I don't need to split everything into sub processes. – Sachin Aravind Apr 27 '22 at 07:53
  • @SachinAravind In your case, `v = open('/etc/redhat-release').read()` is the simplest way. – Xinhe Wang Apr 27 '22 at 07:56
  • Thanks. But my intention is to make Python as an interpreter to communicate with your OS and execute any command that end user prefers, that too in real time. – Sachin Aravind Apr 27 '22 at 07:58
  • @SachinAravind All right, but, just as a reminder, remember to check if the command entered by user is safe before execution. DO NOT trust user input all the time. – Xinhe Wang Apr 27 '22 at 08:05
  • Even this code is not working: # cat mylinux.py import subprocess import shlex subprocess.run(shlex.split(input("Enter the command:")),capture_output=True).stdout.decode() Output: # python mylinux.py Traceback (most recent call last): File "mylinux.py", line 13, in subprocess.run(shlex.split(input("Enter the command:")),capture_output=True).stdout.decode() AttributeError: 'module' object has no attribute 'run' – Sachin Aravind Apr 27 '22 at 10:05
  • Even the below code is not working. v=subprocess.check_output(shlex.split("ls -lrt"),stdout=subprocess.PIPE) v.stdout – Sachin Aravind Apr 27 '22 at 10:22
  • This is the error: v=subprocess.check_output(shlex.split("ls -lrt"),stdout=subprocess.PIPE) File "/usr/lib64/python2.7/subprocess.py", line 567, in check_output raise ValueError('stdout argument not allowed, it will be overridden.') ValueError: stdout argument not allowed, it will be overridden. – Sachin Aravind Apr 27 '22 at 10:22
  • @SachinAravind You should NOT use Python 2.7 any more since it reached the end of its life on January 1st, 2020! It has been deprecated for more than 2 years. See https://www.python.org/doc/sunset-python-2/ – Xinhe Wang Apr 27 '22 at 16:10
  • Even in Python 3.6, I am getting below error. [root@bteir python_exercise]# python mylinux.py This is an interactive linux session using Python! Here if you want to exit the session, type exit as the input command Traceback (most recent call last): File "mylinux.py", line 13, in v=subprocess.check_output(shlex.split("ls -lrt"),stdout=subprocess.PIPE) File "/usr/lib64/python3.6/subprocess.py", line 348, in check_output raise ValueError('stdout argument not allowed, it will be overridden.') ValueError: stdout argument not allowed, it will be overridden. – Sachin Aravind Apr 28 '22 at 04:04
  • @SachinAravind Yes, you're right. As I mentioned, `capture_out` was introduced in Python 3.7. In version below that you can use `stdout=subprocess.PIPE` instead. – Xinhe Wang Apr 28 '22 at 04:10
  • Can you specify the alteration to be made? v=subprocess.check_output(shlex.split("ls -lrt"),stdout=subprocess.PIPE) v.stdout – Sachin Aravind Apr 28 '22 at 04:31
  • 1
    @SachinAravind `subprocess.check_output` does not need parameter `stdout` but `subprocess.run` does. Both `subprocess.check_output(shlex.split("ls -lrt")).decode()` and `subprocess.run(shlex.split("ls -lrt"), stdout=subprocess.PIPE).stdout.decode()` work fine on my Python 3.6 – Xinhe Wang Apr 28 '22 at 04:45
  • Thanks. This works! `v=subprocess.run(shlex.split("ls -lrt"), stdout=subprocess.PIPE).stdout.decode() print(v)` – Sachin Aravind Apr 28 '22 at 04:51
  • @SachinAravind Congratulations! – Xinhe Wang Apr 28 '22 at 04:53
  • In case if the shell is changing or if I am switching to some other user, the script ceases the execution. Is there any way I can make the script executes completely? – Sachin Aravind Apr 28 '22 at 07:05
  • And also for the below command, `echo "this is the command execution" >> hi` it is just giving the output as follow, instead of appending the echo output to the file hi. `this is the command execution >> hi` – Sachin Aravind Apr 28 '22 at 09:02
  • @SachinAravind Use `subprocess.run(['sh', '-c', 'echo "this is the command execution" >> hi'], ...)` instead of `shlex`. `>>` is a part of the syntax of bash-like shells. – Xinhe Wang Apr 28 '22 at 10:23