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

Getting raw command output for processing #9

Open
kamermans opened this issue Mar 8, 2014 · 4 comments
Open

Getting raw command output for processing #9

kamermans opened this issue Mar 8, 2014 · 4 comments

Comments

@kamermans
Copy link

First, thanks for the extraordinary package :)

Secondly, inside my tasks, I would like to access the raw output from the SSH command that was run so I can make decisions. After a couple hours of trying to creatively inject my custom CapturedOutput outputter into the doRun() function, I realized that this outputter is not used for command output, since the Shunt object has its own outputter that it got during instantiation. It seems to me that getting the raw output would be useful for others as well, so why not do one of these:

  1. Save the raw output in the Shunt object, then provide access so the task can run() something, then grab the output.
  2. Add a third parameter to Shunt::run() called OutputInterface $command_output so we can pass in a custom Outputter to grab the raw output of the command.
  3. Add the raw output to the ArbitraryCommand itself, along with the return value and maybe some timing information so you can do ::getDuration() ::getStartTime() ::getEndTime(), etc, from the command.

I think no. 1 would be the most convenient, what you do you think?

Here's my very basic CapturedOutput class that I referenced:

    <?php

    namespace ScientiaMobile\UserManager\Output;

    use Symfony\Component\Console\Formatter\OutputFormatterInterface;
    use Symfony\Component\Console\Output\Output;

    class CapturedOutput extends Output {

            private $output;

            public function __construct($verbosity = self::VERBOSITY_NORMAL) {
                    $this->flushOutput();
                    parent::__construct($verbosity, false, null);
            }

            public function getOutput() {
                    return $this->output;
            }

            public function getOutputLines() {
                    return explode("\n", $this->output);
            }

            public function flushOutput() {
                    $this->output = '';
            }

            protected function doWrite($message, $newline) {
                    $this->output .= $message;
                    if ($newline) $this->output .= "\n";
            }
    }
@kamermans
Copy link
Author

I've forked Shunt and added the functionality I needed, but I don't want to send a pull request until I understand something first. Here's my commit:

kamermans@cc53f1f

Note that in my fork, I am silencing the output for commands that are run with retval=TRUE since I'm assuming the output is not relevant. It is not totally clear to me what retval even contains, but it doesn't seem to be the command's return value unless I'm missing something.

@toopay
Copy link
Member

toopay commented Mar 8, 2014

Hey @kamermans

It is not totally clear to me what retval even contains, but it doesn't seem to be the command's return value unless I'm missing something.

Passing second argument to run method will return the final result. So retval, in console/terminal app - afaik - was simply integer value that tell us whether the execution was fail or success (1 = fail, 0 = no error occurs).

The output stream itself (or raw output) will be printed via php standard output. If we want to store these output stream somewhere, there should be a valid use-case. Can you give one?

@kamermans
Copy link
Author

Hi @toopay

Thanks for the quick response. My use case is as follows. I'm building a user management system that keeps track of which users and SSH keys are in use at each server. Here is a task that I'm using with my fork of Shunt right now to accomplish this:

'tasks' => array(
    'show_keys' => function($s) use ($manager) {
        $host = $s->getSession()->getHost();

        $s->printOut("Processing /etc/passwd");
        $s->run('cat /etc/passwd', true);
        $users = parsePasswd($s->getStdOut());

        $s->printOut("Fetching User Keys");
        foreach ($users as $username => $user) {
            if (in_array($user->shell, array(
                '/bin/false',
                '/usr/sbin/nologin',
            ))) continue;
            $s->run('cat '.escapeshellarg($user->home).'/.ssh/authorized_keys* 2>/dev/null', true);
            if (trim($s->getStdOut()) == '') continue;
            $manager->addUserKey($host, $user, $s->getStdOut(true));
        }
    },
),

Note the use of $s->getStdOut() to pull the standard output. I think this would make Shunt a very useful tool in other libraries like mine. Especially if you can parallelize the command execution :)

@toopay
Copy link
Member

toopay commented Mar 9, 2014

I'll keep this issue open. Will work on it these week.

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

No branches or pull requests

2 participants