Skip to content

Run an external command and collect stdout #108

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

Closed
dtolnay opened this issue May 17, 2017 · 15 comments · Fixed by #122
Closed

Run an external command and collect stdout #108

dtolnay opened this issue May 17, 2017 · 15 comments · Fixed by #122

Comments

@dtolnay
Copy link
Member

dtolnay commented May 17, 2017

Does anyone have non-contrived examples? Some ideas:

  • nm to list symbols in the current executable
  • git rev-parse --verify HEAD
  • some ImageMagick command
@budziq
Copy link
Collaborator

budziq commented May 17, 2017

  • cat /proc/cpuinfo or cat /proc/vmstat
  • ls /tmp
  • df
  • groups

@dtolnay
Copy link
Member Author

dtolnay commented May 17, 2017

By non-contrived I mean things that you couldn't just do in ordinary Rust. So I would prefer not to show cat /proc/cpuinfo or ls /tmp because you would just write those using the standard library.

df isn't the best for an example because it would need a lot of code to parse and do anything useful with the output.

groups could be a good one! I think the libc crate has a function to list groups but unclear whether that is more or less complicated than parsing the command output.

@budziq
Copy link
Collaborator

budziq commented May 17, 2017

oh now I get it. How about these then:

  • uname -a
  • lsblk
  • history
  • mount
  • journalctl

something simple yet not easily doable with std

@Michael-F-Bryan
Copy link
Contributor

Do we want to make sure the command used is commonly available on both Windows and unix systems? If so that probably limits this to commands like git and rustc -Z because I doubt most Windows people would have GNU Binutils (nm) installed.

@dtolnay
Copy link
Member Author

dtolnay commented May 18, 2017

Yes good call, that would be ideal.

@Michael-F-Bryan
Copy link
Contributor

Michael-F-Bryan commented May 18, 2017

Would it be acceptable to pull in the regex crate as a dependency? Regex is pretty much the swiss army knife of text manipulation, so I imagine the cookbook will include several uses of it anyway.

@dtolnay
Copy link
Member Author

dtolnay commented May 18, 2017

Yes that would be fine! What do you have in mind?

@Michael-F-Bryan
Copy link
Contributor

Off the top of my head, parsing something like git log --oneline into a commit hash, some optional tags or branch names, and its message?

61d6ac0 (HEAD -> master) Added a collapsible sidebar
2318e2b Added chart.js and a Chart component
4d0fb2a Started setting up the component tree
06fa097 Initial ReactJS app skeleton

I'm happy to make a PR for this one when I get home.

@dtolnay
Copy link
Member Author

dtolnay commented May 18, 2017

Okay that seems reasonable to me.

If someone wanted to get commit hashes and messages would you feel comfortable recommending this shell command + regex approach over using the git2 crate?

@Michael-F-Bryan
Copy link
Contributor

For something reasonably simple like this I'd recommend parsing the process's output like we're doing here. Anything more complex though and it's probably going to be easier to use the library.

As it is, this should just be a couple lines of filter_map() and map() corresponding to what you'd usually do in bash, so pulling in git2 is probably overkill.

@dtolnay
Copy link
Member Author

dtolnay commented May 18, 2017

Makes sense! I look forward to the PR.

@Michael-F-Bryan
Copy link
Contributor

I've made an initial implementation (gist). @dtolnay, any chance you can give it a look over and see if it can be improved?

In particular, the error handling on line 32 (where I'm creating a new io::Error) feels a little odd. I was thinking of implementing my own error type or using error_chain!{...} but that's adding a lot of boilerplate to an already lengthy example.

@budziq
Copy link
Collaborator

budziq commented May 18, 2017

@Michael-F-Bryan This looks great!.
I would have only one small nit:
Please see our error handling section section. Using error_chain! is the promoted error handling way (please do not worry about the noise we are working on it https://github.com/brson/rust-cookbook/pull/107).
Also could you update the example to the form

fn run() -> Result<()> {
//actual main
    Ok(())
}

quick_main!(run);

The rationale is neatly explained in https://github.com/brson/rust-cookbook/pull/53#issuecomment-300244571

@Michael-F-Bryan
Copy link
Contributor

Cheers for the links, I've updated the gist and added error_chain to make error handling nicer/more idiomatic.

Do you think that intermediate Commit type is still necessary now that I've put everything into a single run() function? I could just use a tuple, but that loses a bit of the readability gained by having named fields.

Also, which section would this belong in? I was thinking of adding it to the bottom of the "basics" section, but if we end up adding examples like piping one subprocess's output into another or running a child process in the background and doing other things while you wait for it to exit, it may be worth creating a new section in the cookbook. Thoughts?

@budziq
Copy link
Collaborator

budziq commented May 18, 2017

The gist looks excellent, please create a PR.

I would add the example to the "basics" section for now. Once we have more examples we will think about how these should be split.

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

Successfully merging a pull request may close this issue.

3 participants