Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoke hangs in input when using in_stream to pass data to crontab #602

Closed
gertjanol opened this issue Dec 7, 2018 · 2 comments
Closed

Comments

@gertjanol
Copy link

I'm trying to manipulate a users crontab with an invoke task. Direct access to a crontab is not allowed, so you have to use the crontab-tool. The process is simple: use crontab -l to read the contents. manipulate it and write is back using (basically) echo "new-contents" | crontab.
When using the in_stream-parameter to ctx.run with the new contents (in a StringIO object), the invoke task hangs. Using strace on the process I can see that it's waiting on input.

A simple implementation using subprocess.Popen works perfectly.

It's very easy to reproduce (this will overwrite your local crontab, make sure it doesn't contain anything important!):

$ mkdir invoke-test
$ cd invoke-test
$ mkvirtualenv -ppython2.7 invoke-test
$ pip install invoke==1.2.0

$ cat <<EOM>tasks.py
from StringIO import StringIO
from subprocess import Popen, PIPE

from invoke import task

crontab = '* * * * * echo shibby\n'


@task
def hangs(c):
    c.run('crontab', in_stream=StringIO(crontab))


@task
def works(c):
    p = Popen(['crontab'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    _, _ = p.communicate(crontab)
    p.poll()
EOM
$ inv -l
Available tasks:

  hangs
  works

$ inv works
$ crontab -l
* * * * * echo shibby
$ crontab -r
$ inv hangs
<nothing>

Python 2 (.7) or Python 3 (.6) makes no difference. Also the fix-everything-pty=true trick didn't help.

Maybe I don't understand how to use the in_stream parameter or this may not be the intended use, but I'd love some feedback!

@mathieulongtin
Copy link

It appears that run() doesn't close stdin once the in_stream is at EOF. You can test this trivially:

run("cat -n", in_stream=io.BytesIO(b"some\nlines\n"))

This will block.

The other weird thing is that it appears that it feeds stdin one character at a time.

@bitprophet
Copy link
Member

This feels like a duplicate of #552, rolling into that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants