0

I want to grep a Linux Screen ID in Python to check if this Screen exists. I would like to convert my os.system command to subprocess command.

From this:

os.system('screen -ls | grep -i ' + INSTANCE_NAME + ' >/dev/null')

to this:

subprocess.check_call(['screen', '-ls', '|', 'grep', '-i', INSTANCE_NAME])

The os.system command works fine, but not the subprocess command. And what are the differences between subprocess.run, subprocess.call and subprocess.check_call? Can someone help me out?

I'm using Python 3.10 on Linux Ubuntu Server 20.04 LTS

Niklas
  • 436
  • 1
  • 4
  • 16

1 Answers1

0

The pipe | is a shell command that connects the output of a process to the input of another. If you want to use it in subprocess, you have to tell the subprocess function that you want to run the command in a shell like this:

subprocess.check_call('screen -ls | grep -i ' + INSTANCE_NAME, shell=True)

If you use this, you should take into account the security considerations of the shell invocation. If you want to achieve the same thing without a shell, you must use two subprocesses. Here is an example:

p1 = subprocess.Popen(["screen", "-ls"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(
    ["grep", "-i", INSTANCE_NAME], stdin=p1.stdout, stdout=subprocess.PIPE
)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0].decode()

(See https://docs.python.org/3/library/subprocess.html#replacing-shell-pipeline)

And what are the differences between subprocess.run, subprocess.call and subprocess.check_call? Can someone help me out?

The documentation provides extensive information about the difference between these functions. The TL;DR is:

  1. call and check_call are part of the old high-level API while run is the new recommended approach to invoke subprocesses.
  2. call: runs a command and returns its return code
  3. check_call: like call but raises an exception if the return code is not 0
  4. run: well, you have access to the return code, the output, you can raise for non-zero codes, etc, etc. The documentation has all the information.
hamdanal
  • 477
  • 3
  • 10
  • Note that rather than actually piping `screen` to `grep`, you could just run `screen` alone and search the results yourself (writing code equivalent to `grep` in Python is trivial). – ShadowRanger Dec 24 '21 at 20:30
  • @Niklas Glad you found the answer useful. @ShadowRanger you are right, I would use python string operations and/or the `re` module instead of `grep`. That said I wrote the answer this way because the second subprocess could be anything, not necessarily `grep`. – hamdanal Dec 24 '21 at 20:35
  • It's a good answer, but we probably have hundreds of duplicates of the question in the knowledge base already. Do mind the note in the Answer Well-Asked Questions section of [How to Answer](https://stackoverflow.com/help/how-to-answer) about questions that have been "asked and answered many times before". – Charles Duffy Dec 24 '21 at 21:00
  • How would this looks like when I don't use `grep` and just use python and without using a shell? – Niklas Dec 24 '21 at 22:18