podman-py icon indicating copy to clipboard operation
podman-py copied to clipboard

[BUG] empty stdout/stderr for `exec_run` on macOS

Open aparcar opened this issue 11 months ago • 9 comments

Hi, I'm running Podman Machine on a MacBook and everything works fine except the exec_run, the output is always empty. Below an example which works on Linux machines:

>>> import podman
>>> client = podman.PodmanClient()
>>> client.images.list()
[<Image: 'docker.io/library/alpine:latest'>]
>>> client.version()
{'Platform': {'Name': 'linux/arm64/fedora-41'}, 'Components': [{'Name': 'Podman Engine', 'Version': '5.4.0-dev-234c41c80', 'Details': {'APIVersion': '5.4.0-dev-234c41c80', 'Arch': 'arm64', 'BuildTime': '2025-01-22T00:00:00Z', 'Experimental': 'false', 'GitCommit': '', 'GoVersion': 'go1.23.4', 'KernelVersion': '6.12.7-200.fc41.aarch64', 'MinAPIVersion': '4.0.0', 'Os': 'linux'}}, {'Name': 'Conmon', 'Version': 'conmon version 2.1.12, commit: ', 'Details': {'Package': 'conmon-2.1.12-3.fc41.aarch64'}}, {'Name': 'OCI Runtime (crun)', 'Version': 'crun version UNKNOWN\ncommit: b143d9ea7cfea9de44222d7fcfb7f55c21ba8060\nrundir: /run/user/501/crun\nspec: 1.0.0\n+SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL', 'Details': {'Package': 'crun-1.19.1-1.20250121161049663014.main.23.ga2d140d.fc41.aarch64'}}], 'Version': '5.4.0-dev-234c41c80', 'ApiVersion': '1.41', 'MinAPIVersion': '1.24', 'GitCommit': '', 'GoVersion': 'go1.23.4', 'Os': 'linux', 'Arch': 'arm64', 'KernelVersion': '6.12.7-200.fc41.aarch64', 'BuildTime': '2025-01-22T00:00:00Z'}
>>> container = client.containers.create("alpine", command=["sleep", "1000"])
>>> container.start()
>>> ret, out = container.exec_run("echo 42", demux=True)
>>> ret
0
>>> out
(b'', b'')

Any ideas?

aparcar avatar Jan 27 '25 18:01 aparcar

Generally stdout works when using the example below:

>>> client.containers.run("alpine", ["echo", "42"])
b'42\n'

aparcar avatar Jan 27 '25 18:01 aparcar

hey @aparcar , thanks for the report. I can try to investigate it on Windows (since podman is provided via machine), but I don't have a mac, so it will take more time if it's mac only. I'll follow up if I can get it on Windows or I'll ask for more info :)

@Edward5hen do you have a mac?

inknos avatar Jan 27 '25 18:01 inknos

Turns out this is an issue when using SSH as connection. I tried using the UNIX socket and it works as expected...

aparcar avatar Feb 15 '25 21:02 aparcar

Adding more logs from my machine for review.

Hardware: Apple M1 Pro
macOS: Sequoia 15.3.2
Python: 3.11.9
Architecture: arch64

Environment script env.py

#!/usr/bin/env python3

from dataclasses import dataclass
from json import loads
from subprocess import CalledProcessError, run
from typing import List

@dataclass
class Connection:
  default: bool
  host: str
  identity: str
HOST: str
IDENTITY: str

try:
  output: str = (
    "["
    + ",".join(
      run(
        [
          "podman",
          "system",
          "connection",
          "list",
          "--format",
          '{"host": "{{.URI}}", "identity": "{{.Identity}}", "default": {{.Default}}}',
        ],
        capture_output=True,
        check=True,
      )
      .stdout.decode("utf-8")
      .rstrip()
      .split("\n")
    )
    + "]"
  )
  connections: List[Connection] = [Connection(**connection) for connection in loads(output)]
  default_connection: Connection = next(filter(lambda connection: connection.default, connections))
  HOST = default_connection.host
  IDENTITY = default_connection.identity
except CalledProcessError:
  HOST = ""
  IDENTITY = ""

Runtime

$ python -i env.py
>>> import podman
>>> client = podman.PodmanClient(base_url=HOST, identity=IDENTITY)
>>> client.images.list()
[<Image: 'docker.io/library/alpine:latest'>]
>>> container = client.containers.create("alpine", command=["sleep", "1000"])
>>> container.start()
>>> ret, out = container.exec_run("echo 42", demux=True)
>>> ret
0
>>> out
(None, None)

aekasitt avatar Apr 25 '25 07:04 aekasitt

More context, running latest code from branch main as of date

>>> ret, out = container.exec_run("echo 42")
>>> ret
0
>>> out
b''

aekasitt avatar Apr 25 '25 07:04 aekasitt

MOAR CONTEXT: Spam until it works.

$ python -i env.py
... steps from op...
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'')
>>> container.exec_run("echo 42", tty=True)
(0, b'42\r\n')

aekasitt avatar Apr 25 '25 10:04 aekasitt

Without tty flag:

$ python -i env.py
... steps from op...
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'')
>>> container.exec_run("echo 42")
(0, b'\x01\x00\x00\x00\x00\x00\x00\x0342\n')

aekasitt avatar Apr 25 '25 11:04 aekasitt

I'm using Debian linux, and I met the same problem.

choems avatar Oct 27 '25 05:10 choems

I'm using Debian linux, and I met the same problem.

I finally fixed this by manually create ssh tunnel instead of using the one automatically created.

choems avatar Oct 27 '25 11:10 choems