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

plumbum hides stderr of pipes #240

Open
hashbrowncipher opened this issue Nov 9, 2015 · 12 comments
Open

plumbum hides stderr of pipes #240

hashbrowncipher opened this issue Nov 9, 2015 · 12 comments
Assignees
Labels
Milestone

Comments

@hashbrowncipher
Copy link
Contributor

Type "help", "copyright", "credits" or "license" for more information.
>>> from plumbum.cmd import cat, head
>>> from plumbum import FG
>>> cat['/dev/urndom'] & FG(1)
/bin/cat: /dev/urndom: No such file or directory
>>> (cat['/dev/urndom'] | head['-c', '10']) & FG(retcode=1)
>>>

I would expect to see the standard error output of cat printed to the stderr of the Python process. For instance, zsh shows this:

❯❯❯ /bin/cat /dev/urndom | head -c10
/bin/cat: /dev/urndom: No such file or directory
@henryiii
Copy link
Collaborator

I'll try to look at these soon! Hoping it's an easy fix. Feel free to dig around a bit, would start in plumbum/commands.

@henryiii henryiii added the Bug label Nov 10, 2015
@henryiii henryiii added this to the v1.6.1 milestone Nov 10, 2015
@henryiii henryiii self-assigned this Nov 10, 2015
@henryiii
Copy link
Collaborator

I've got a fix for this, will commit in a day or two.

henryiii added a commit to henryiii/plumbum that referenced this issue Nov 10, 2015
@hashbrowncipher
Copy link
Contributor Author

Hey, I don't see code for this in master. Did something prevent you from merging the change you had?

@henryiii
Copy link
Collaborator

Seems to work...

maya8:plumbum henryiii$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
maya8:plumbum henryiii$ python
Python 3.5.0 |Anaconda 2.4.0 (x86_64)| (default, Oct 20 2015, 14:39:26) 
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from plumbum import FG
>>> from plumbum.cmd import cat, head
>>> cat['/dev/urndom'] & FG(1)
cat: /dev/urndom: No such file or directory
>>> (cat['/dev/urndom'] | head['-c', '10']) & FG(retcode=1)
cat: /dev/urndom: No such file or directory

@henryiii
Copy link
Collaborator

Should also be tested for, now, with py.test, using file descriptor capture:

    @skip_on_windows
    def test_pipe_stderr(self, capfd):
        from plumbum.cmd import cat, head
        cat['/dev/urndom'] & FG(1)
        assert 'urndom' in capfd.readouterr()[1]

        assert '' == capfd.readouterr()[1]

        (cat['/dev/urndom'] | head['-c', '10']) & FG(retcode=1)
        assert 'urndom' in capfd.readouterr()[1]

@thomasshanks
Copy link

@henryiii:
I'm getting this new error:
plumbum.machines.session.SSHCommsChannel2Error: No stderr result detected. Does the remote have Bash as the default shell?
EVERY time I attempt to run a command with a pipe in it, eg.
'echo {} | sudo tee /etc/hostname'.format(hostname)'. (I am also getting this for 'sudo hostname {}'.format(hostname), so I think that this might be an issue that goes beyond use of pipes.) What's the right way to use pipes after this command?

My attempt to work around this was to use "sudo dd of=/etc/hostname <<<'{}'".format(hostname). That didn't work, either. It was met with: plumbum.machines.session.SSHCommsError: No communication channel detected. Does the remote exist?. So was 'sudo sh -c "echo {} > /etc/hostname"'.format(hostname). Is there a right way to do that, as well?

@henryiii henryiii reopened this May 20, 2017
@arunrubrik
Copy link

Any plan to fix this bug ?

@henryiii
Copy link
Collaborator

I'd be happy with a PR :) I won't have time to work on it for at least a couple of weeks or more.

@woky
Copy link

woky commented Jan 22, 2019

It seems it's not just pipes. I'd expect the following to print errors to Python process's sys.stderr:

from plumbum import local

bash = local['bash']['-c']
x = bash('echo foo >&2')
y = bash('ls /123456 || true')

It doesn't print anything though.

@hashbrowncipher
Copy link
Contributor Author

@woky I looked up the docstring for __call__, and found that it says "A shortcut for run(args), returning only the process’ stdout". I was able to get output going to sys.stderr by doing:

>>> bash['ls /123456 || true'] & FG

If instead capturing stderr is preferred, one can do:

>>> bash.run('ls /123456 || true')
(0, '', "ls: cannot access '/123456': No such file or directory\n")

@woky
Copy link

woky commented Jan 25, 2019

I don't want to capture stderr. It should be printed to actual sys.stderr and not discarded. If you do in e.g. Bash

foo=$(ls /12345 || echo foo)

you get stdout into $foo but stderr will still be printed to shell's stderr. Plumbum seems to discard it for no reason.

@henryiii henryiii modified the milestones: v1.6.1, Future ideas Feb 8, 2021
@ThomasHickman
Copy link

One way to workaround this is to just add >= sys.stderr after any ... = local[...] assignments e.g.:

$ python3
Python 3.11.8 (main, Feb 25 2024, 16:39:33) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from plumbum import local
>>> import sys
>>> bash = local['bash']['-c'] >= sys.stderr
>>> x = bash('echo foo >&2')
foo
>>> y = bash('ls /123456 || true')
ls: cannot access '/123456': No such file or directory

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

No branches or pull requests

6 participants