Search code examples
pythonlinuxpipechecksumtee

Why python unable to take care of pipe with tee utility?


I want to run the following command from a python code in a remote machine:

/bin/cat < abc.txt | tee >(echo $(md5sum) > /tmp/abc.md5sum) | some-other-command.

I have to use Cumin to send this command to remote machines. My code is given below:


from multiprocessing import Pipe, Process
import os

import cumin
from cumin import query, transport, transports

from mypackage.RemoteExecution import CommandReturn, RemoteExecution


def run_subprocess(host, command, input_pipe):
    e = CuminExecution()
    result = e.run(host, command)
    input_pipe.send(result)


class CuminExecution(RemoteExecution):
    """
    RemoteExecution implementation using Cumin
    """

    def __init__(self, options={}):
        self._config = None
        self.options = options

    @property
    def config(self):
        if not self._config:
            self._config = cumin.Config()

        return self._config

    def format_command(self, command):
        if isinstance(command, str):
            return command
        else:
            return ' '.join(command)

    def run(self, host, command):
        hosts = query.Query(self.config).execute(host)
        if not hosts:
            return CommandReturn(1, None, 'host is wrong or does not match rules')
        target = transports.Target(hosts)
        worker = transport.Transport.new(self.config, target)
        worker.commands = [self.format_command(command)]
        worker.handler = 'sync'

        return_code = worker.execute()

        for nodes, output in worker.get_results():
            if host in nodes:
                result = str(bytes(output), 'utf-8')
                return CommandReturn(return_code, result, None)

        return CommandReturn(return_code, None, None)

    def start_job(self, host, command):
        output_pipe, input_pipe = Pipe()
        job = Process(target=run_subprocess, args=(host, command, input_pipe))
        job.start()
        input_pipe.close()
        return {'process': job, 'pipe': output_pipe}

    def monitor_job(self, host, job):
        if job['process'].is_alive():
            return CommandReturn(None, None, None)
        else:
            result = job['pipe'].recv()
            job['pipe'].close()
            return result

    def kill_job(self, host, job):
        if job['process'].is_alive():
            job['process'].terminate()

    def wait_job(self, host, job):
        job['process'].join()
        result = job['pipe'].recv()
        job['pipe'].close()
        return result


src_command = "/bin/cat < abc.txt | tee >(echo $(md5sum) > /tmp/abc.md5sum) | some-other-command"
result = CuminExecution.run(host, src_command)

When I run the command /bin/cat < abc.txt | tee >(echo $(md5sum) > /tmp/abc.md5sum) | some-other-command from the terminal, it is working as expected. But when I try to run it using python3 using the above code, It can process all the commands properly except the writing to /tmp/abc.md5sum part! After the run, the file abc.md5sum contains an incorrect hash.

Can somebody help me with this issue?


Solution

  • I have changed the command this way:

    /bin/cat < abc.txt | tee >(md5sum > /tmp/abc.md5sum) | some-other-command

    and it is working now! Thank you all for your help!