pyinfra-dev / pyinfra

pyinfra turns Python code into shell commands and runs them on your servers. Execute ad-hoc commands and write declarative operations. Target SSH servers, local machine and Docker containers. Fast and scales from one server to thousands.
https://pyinfra.com
MIT License
3.91k stars 383 forks source link

files.download doesn't overwrite file #746

Closed drewp closed 2 years ago

drewp commented 2 years ago

I haven't tried to repro this. Hopefully the evidence from my shell history is useful.

Running this from host 'bang':

files.download(
        src=f'https://github.com/rancher/k3s/releases/download/{k3s_version}/{tail}',
        dest='/usr/local/bin/k3s',
        user='root',
        group='root',
        mode='755',
        cache_time=43000,
    )

said this:

    [dash] curl: (23) Failure writing output to destination
    [dash] Error
    [bang] Success
    [slash] Success

until I ran sudo rm /usr/local/bin/skaffold on dash. Then:

    [bang] No changes
    [slash] No changes
    [dash] Success

and now dash has this root-owned file:

-rwxr-xr-x 1 root root 60297216 Jan 31 23:20 /usr/local/bin/skaffold

I think dash should have worked the first time, like slash and bang did.

Meta

drewp commented 2 years ago

Still hitting this. I found this in strace on the machine that fails:

openat(AT_FDCWD, "/usr/local/bin/skaffold", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 ETXTBSY (Text file busy)

Indeed, I have some running skaffold processes on dash.

One fix is that pyinfra could download to another file and then mv it on top of the desired path.

Fizzadar commented 2 years ago

Thanks for digging into this @drewp - think the download then mv method is the best solution, aligns with how files.put works as well 👍.

Fizzadar commented 2 years ago

I just released v1.6.2 which contains this change (https://github.com/Fizzadar/pyinfra/commit/5944d8e54252dca29d4dbf73592795d9cc13d871).