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

Command output not found in message property #593

Open
FatherShawn opened this issue Jun 9, 2017 · 8 comments
Open

Command output not found in message property #593

FatherShawn opened this issue Jun 9, 2017 · 8 comments

Comments

@FatherShawn
Copy link

Steps to reproduce

I recently updated from 1.0.6 to 1.0.8. I updated the following code for the changes in result output by providing calls to provideOutputdata().

 $result = $this->taskExec('docker ps --format "{{.Names}}"')->run();
    if ($result->wasSuccessful()) {
      $result->provideOutputdata();
      $running = !(strpos($result->getOutputData(), 'dnsmasq') === FALSE);
    }
    if (!$running) {
      $result = $this->taskExec('docker ps -a --format "{{.Names}}"')->run();
      $result->provideOutputdata();
      if ($result->wasSuccessful() && !(strpos($result->getOutputData(),
            'dnsmasq') === FALSE)
      ) {
        // Container exists but is stopped.
        $this->say('Container exists but is stopped.');
        $this->taskDockerRemove('dnsmasq')->run();
      }

Expected behavior

I see the results of my TaskExec in the terminal, so the command is running. It should be captured to the message property of the the Result object.

Actual behavior

In this instance result->getOutputData() still returns an empty string.

System Configuration

macOS 10.12.5

PHP 5.6.30 (cli) (built: Mar 11 2017 09:56:27)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Xdebug v2.5.3, Copyright (c) 2002-2017, by Derick Rethans

@FatherShawn
Copy link
Author

I'm beginning to think that something upstream has changed. Using xdebug I find that \Symfony\Component\Process\Process::getOutput returns empty on this command. Other Robo process are returning output just fine. So either Symfony or Docker may have changed, although it still seems off that I have terminal output but nothing getting captured.

@greg-1-anderson
Copy link
Member

This was my fault -- I introduced a breaking change.

Can you switch to $result->getMessage()? I'll back out the breaking change if this is too much trouble for folks, but the way it is now is much better for result propagation in task collections.

@FatherShawn
Copy link
Author

Thanks for the prompt reply, Greg!

I encountered the breaking change and worked around with $result->provideOutputData but the switch to $result->getMessage makes for simpler code. My other commands that examine output are working.

However it does not remedy this issue - $result->message is empty on both these tasks. I refactored to simpler output, but still no message.

  /**
   * Launches the dnsmasq container if it is not running.
   */
  protected function setMacDnsmasq() {
    $running = FALSE;
    $this->setMacDockerEnv();
    $result = $this->taskExec('docker ps -aq --filter "name=dnsmasq" --filter status=running')->run();
    if ($result->wasSuccessful()) {
      $running = !(strlen($result->getMessage()) == 0);
    }
    if (!$running) {
      $result = $this->taskExec('docker ps -aq --filter "name=dnsmasq"')->run();
      if ($result->wasSuccessful() && !(strlen($result->getMessage()) == 0)
      ) {
        // Container exists but is stopped.
        $this->say('Container exists but is stopped.');
        $this->taskDockerRemove('dnsmasq')->run();
      }
      $ip = $this->getDockerMachineIp();
      $result = $this->taskDockerRun('andyshinn/dnsmasq:2.76')
        ->name('dnsmasq')
        ->detached()
        ->optionList('publish', ['53535:53/tcp', '53535:53/udp'])
        ->option('cap-add', 'NET_ADMIN')
        ->exec("--address=/dpulp/$ip")
        ->printOutput(FALSE)
        ->run();
      if ($result instanceof Result && $result->wasSuccessful()) {
        $this->setResolverFile();
        $this->io()->success('DP Docker DNS service started.');
        $launch = $this->confirm('Would you also like to launch the site created by this project?');
        if ($launch) {
          $this->dockerComposeMac();
        }
      }
    }
    else {
      $this->io()->note('DNS service is already running.');
    }
  }

This utility method fails to detect the existing container so it fails:

 [Exec] Running docker ps -aq --filter "name=dnsmasq" --filter status=running
 [Exec] Done in 1.389s
 [Exec] Running docker ps -aq --filter "name=dnsmasq"
74b95b8684dd
 [Exec] Done in 0.899s

 [Docker\Run] Running docker run  --name dnsmasq -d --publish '53535:53/tcp' --publish '53535:53/udp' --cap-add NET_ADMIN --cidfile /var/folders/lf/506vsfs91jb2wcjqz5g8k3880000gr/T/docker_593b34c66b0da.cid andyshinn/dnsmasq:2.76 --address=/dpulp/192.168.64.91
 [Docker\Run]    Time 0.77s
 [Docker\Run]  Exit code 125  Time 0.77s

I'll keep trying to understand why other processes capture a message but not this one.

@FatherShawn
Copy link
Author

Got it!

My working commands that examine output also use ->printOutput(FALSE). Chaining this method call causes the message property to populate.

@obstschale
Copy link

Thx @FatherShawn ->printOutput(FALSE) really helped to get the output. But I think it is a weird behavior that the result is not stored automatically. I expected to see the output but also be able to retrieve it later.

@AlexSkrypnyk
Copy link
Contributor

@greg-1-anderson Could you please explain what is the purpose of isPrinted property? From the name it is not clear whether it means "has already been printed" or "need to capture the output of the command" or "need to output the output of the command" or "need to capture AND output the output of the command". Adding this description to this line would help the community to understand the purpose of the variable and ease the debugging.

ExecTrait::execute() has and output callback that calls writeMessage() in the output adapter, which, in own turn, uses Symfony's write() method to write the message. But this method is based on verbosity level of the output (to console), which should not have any effect on the output of the command is captured by the ExecTrait's function. In other words, whatever the console output verbosity is, we should still capture the command output and store it within Exec task.

@pixelbrackets
Copy link
Contributor

Sidenote: Also received an empty result message and solved it, by adding a interactive(false) call, as seen in the Robo Test Suite:

https://github.com/consolidation/Robo/blob/33a94b132f2ac1dcbfe2cff43acc3a63330bc5de/tests/cli/ExecCest.php#L9-L10

@prudloff-insite
Copy link
Contributor

I can confirm this is still a problem with Robo 1.5.0. When using getMessage(), we have to make sure the shell is non-interactive by either:

  • Calling ->interactive(false) on the exec task
  • Using Ssh::configure('interactive', FALSE); for SSH tasks
  • Forcing the shell calling robo to be non-interactive (for example robo foo|cat)

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

6 participants