Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cat blocking when called via subprocess.Popen()

Im having a unexpected behaviour of the linux cat when its called via subprocess.Popen().

The Python script is structured like such:

import os, subprocess

def _degrade_child_rights(user_uid, user_gid):
    def result():
        os.setgid(user_gid)
        os.setegid(user_gid)
        os.setuid(user_uid)
        os.seteuid(user_uid)
    return result

child = subprocess.Popen("cat /home/myuser/myfolder/screenlog.0", 
preexec_fn=_degrade_child_rights(0, 0), shell=True, 
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

When i check the executed shell-command with ps aux | grep cat it shows me that python successfully run the shell-command.

> ps aux | grep cat
root     21236  0.0  0.0   6564   780 pts/1    S    20:49   0:00 /bin/sh -c cat /home/myuser/myfolder/screenlog.0
root     21237  0.0  0.0  11056   732 pts/1    S    20:49   0:00 cat /home/myuser/myfolder/screenlog.0
root     21476  0.0  0.0  15800   936 pts/1    S+   20:52   0:00 grep --color=auto cat

However, the cat command never finishes.

I also outsourced the cat $file command to a bash-script. Then bash executes my cat-call, but also blocks.

When i manually execute cat $file it runs like expected, so a not existing EOF at the end of the file is also impossible.

I think, the '/bin/sh -c' added by Popen messes somehow with the correct execution of cat $file.

Can i somehow prevent this?

like image 626
3 revs Avatar asked Nov 23 '25 15:11

3 revs


1 Answers

You might want to try the communicate method for the Popen object:

Popen.communicate(input=None) Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child.

communicate() returns a tuple (stdoutdata, stderrdata).

Note that if you want to send data to the process’s stdin, you need to create the Popen object with stdin=PIPE. Similarly, to get anything other than None in the result tuple, you need to give stdout=PIPE and/or stderr=PIPE too.

Note The data read is buffered in memory, so do not use this method if the data size is large or unlimited.

There is more info in the subprocess python doc

like image 187
Austin Yates Avatar answered Nov 25 '25 04:11

Austin Yates