Python脚本在Docker容器中执行带重定向的echo命令无法生成目标文件的问题求助
echo content > /tmp/foo in a Docker container via exec_run? Problem Description
I've written the following code to test Docker containers with unittest:
import subprocess import docker import unittest class DockerContainerHost(object): def execute(self, command): self._container.exec_run(command) class Tester(unittest.TestCase): def test_twoHostsOneFile(self): with DockerContainerHost() as host1, DockerContainerHost() as host2: host1.execute('echo content > /tmp/foo') if __name__ == '__main__': unittest.main()
Everything else works fine, but when running host1.execute('/bin/echo content > /tmp/foo'), the file /tmp/foo isn't created in the container. I can successfully create an empty file with touch /tmp/foo, but I need to generate a file with specified content. How can I fix this?
Solution
Ah, I see the issue here! When you use exec_run without enabling shell mode, the redirection operator > isn't being interpreted by a shell—it's just passed as a literal argument to the echo command. That's why touch works (it doesn't need shell processing) but your echo command fails to create the file.
Here are a few reliable fixes:
1. Enable shell execution in exec_run
Modify your execute method to run the command through a shell. This lets the shell handle the redirection:
def execute(self, command): # Add shell=True to let the shell process redirection self._container.exec_run(command, shell=True)
This is the simplest fix for your existing code. Just note that if you're executing untrusted command strings, enabling shell=True can introduce security risks (like shell injection attacks), so use this cautiously if your input isn't controlled.
2. Explicitly call a shell to run your command
If you don't want to enable shell=True globally, you can wrap your command in sh -c to explicitly invoke a shell:
host1.execute('sh -c "echo content > /tmp/foo"')
This achieves the same result as the first fix, but limits shell usage to specific commands. Make sure to handle quotes correctly—if your content includes quotes, you may need to escape them or use different quote delimiters.
3. Write the file directly without relying on shell redirection
For a more secure and programmatic approach, you can write content to the file using the Docker SDK's input stream feature, avoiding shell processing entirely:
class DockerContainerHost(object): def execute(self, command): self._container.exec_run(command) def write_file(self, file_path, content): # Use cat with stdin to write content directly to the file exec_result = self._container.exec_run( f'cat > {file_path}', stdin=True, tty=False, detach=False ) # Write the content to the command's stdin exec_result.output.write(content.encode())
Then use it in your test like this:
host1.write_file('/tmp/foo', 'content')
This method is safer because it doesn't involve shell parsing, and it's easier to handle dynamic content without worrying about escaping issues.
内容的提问来源于stack exchange,提问作者PawelBuchajczuk

