3

Iʼve compressed a software pack, which is the Python program with its virtual environment, to a tar archive. Setup algorithm is that unrolling on the target system (Debian 12) is made using sudo tar -x... from a usual shell. Access to the target system, via SSH, is made using paramiko from Python.

If I fully emulate the work from a local archive: tar -C /TARGET/ -xJpf - </STORAGE/the_archive.tar.xz from a local shell (the same user and password, interactive shell and sudo), there is no problem. But when this is made from paramiko, one symlink, for python3.9 itself, is not created, instead Iʼm stably getting an empty file:

root@HOST$ ls -l /TARGET/.venv/bin
<... other programs ...>
lrwxrwxrwx 1 root root    9 Mar 31 09:44 python -> python3.9
lrwxrwxrwx 1 root root    9 Mar 31 09:44 python3 -> python3.9
---------- 1 root root    0 Mar 31 10:47 python3.9
<... other programs ...>

What is expected that the last reported line really is (and is if unrolling manually):

lrwxrwxrwx 1 root root   18 Mar 31 09:44 python3.9 -> /usr/bin/python3.9

The archive seems correctly specifying the link:

user@host> tar tvf /STORAGE/the_archive.tar.xz | fgrep bin/python
lrwxrwxrwx root/root         0 2026-03-31 09:44 ./.venv/bin/python -> python3.9
lrwxrwxrwx root/root         0 2026-03-31 09:44 ./.venv/bin/python3 -> python3.9
lrwxrwxrwx root/root         0 2026-03-31 09:44 ./.venv/bin/python3.9 -> /usr/bin/python3.9

I donʼt see other difference in results; if I manually replace the empty file with the proper symlink, the program starts working.

I canʼt find other difference in conditions beside the direct remote execution in a non-interactive shell (in paramiko I call exec_command for this and feed the archive to stdin):

channels = shell.exec_command(b"sudo tar -C /TARGET -xJpf -\n")

What really can affect the tar behavior and how to make it create the proper symlink?

Details of sotfware: target host: Debian 12 (bookworm); tar version 1.34+dfsg-1.2+deb12u1. Source host: paramiko 4.0.0 under Python 3.11.

3
  • Why are you using -xJpf - </STORAGE/the_archive.tar.xz instead of -xJpf /STORAGE/the_archive.tar.xz ? Commented 16 hours ago
  • 1
    @DanielT For the target mode, the archive is sent over SSH, it isnʼt preliminarily stored locally. For testing, I emulate the target mode as close as possible. Commented 16 hours ago
  • Does base64-encoding the archive work? In case something is messing with NUL or non-utf-8 bytes Commented 16 hours ago

1 Answer 1

3

Fixed by explicit closing of stdin channel in paramiko after sending the archive bytes.

channels = client.exec_command(...)
stdin = channels[0]
with open(archive_path, "rb") as pca:
    while True:
        block = pca.read(BLOCKSIZE)
        if not block:
            break
        stdin.write(block)
stdin.close() ## <-- added this

It seems tar is postponing finalization of some details to end of the whole input processing, and the channel object was hanging in Python memory.

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.