rust_shell/
lib.rs

1// Copyright 2017 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! # Rust shell - shell script written in rust.
16//!
17//! This is not an officially supported Google product
18//!
19//! Rust shell is a helper library for std::process::Command to write shell
20//! script like tasks in rust. The library only works with unix-like operation
21//! systems.
22//!
23//! ## Run command
24//!
25//! `run!` macro creates a ShellCommand instance which you can run by `run()`
26//! method.
27//!
28//! ```
29//! #[macro_use] extern crate shell;
30//!
31//! # fn main() {
32//! // Run command by cmd! macro
33//! cmd!("echo Hello rust shell!").run().unwrap();
34//!
35//! // Contain white space or non-alphabetical characters
36//! cmd!("echo \"%$#\"").run().unwrap();
37//!
38//! // Pass an argument
39//! let name = "shell";
40//! cmd!("echo Hello rust {}!", name).run().unwrap();
41//!
42//! // Extract environment variable
43//! cmd!("echo HOME is $HOME").run().unwrap();
44//! # }
45//! ```
46//! ## ShellResult
47//!
48//! The return value of `ShellCommand#run()` is `ShellResult` which is `Ok(_)`
49//! only when the command successfully runs and its execution code is 0, so you
50//! can use `?` operator to check if the command successfully exits or not.
51//!
52//! ```
53//! #[macro_use] extern crate shell;
54//! use shell::ShellResult;
55//!
56//! # fn main() {
57//! #   shell_function().unwrap();
58//! # }
59//! fn shell_function() -> ShellResult {
60//!   cmd!("echo Command A").run()?;
61//!   cmd!("echo Command B").run()?;
62//!   shell::ok()
63//! }
64//! ```
65//!
66//! ## Output string
67//!
68//! ShellCommand has a shorthand to obtain stdout as UTF8 string.
69//!
70//! ```
71//! #[macro_use] extern crate shell;
72//!
73//! # fn main() {
74//! assert_eq!(cmd!("echo OK").stdout_utf8().unwrap(), "OK\n");
75//! # }
76//! ```
77//!
78//! ## Spawn
79//!
80//! ShellCommand has `spawn()` method which runs the command asynchronously and
81//! returns `ShellChild`.
82//!
83//! ```
84//! #[macro_use] extern crate shell;
85//! extern crate libc;
86//! use shell::ShellResultExt;
87//!
88//! # fn main() {
89//! // Wait
90//! let child = cmd!("sleep 2").spawn().unwrap();
91//! child.wait().unwrap();
92//!
93//! // Signal
94//! let child = cmd!("sleep 2").spawn().unwrap();
95//! child.signal(libc::SIGINT);
96//! let result = child.wait();
97//! assert!(result.is_err(), "Should be error as it exits with a signal");
98//! assert!(result.status().is_ok(), "Still able to obtain status");
99//! # }
100//! ```
101//!
102//! ## Thread
103//!
104//! If you would like to run a sequence of commands asynchronously,
105//! `shell::spawn` creates a thread as well as `std::thread::spawn` but it
106//! returns `ShellHandle` wrapping `std::thread::JoinHandle`.
107//!
108//! `ShellHandle#signal()` is used to send a signal to processes running on the
109//! thread.  It also stops launching a new process by `ShellComamnd::run()` on
110//! that thread.
111//!
112//! ```
113//! #[macro_use] extern crate shell;
114//! extern crate libc;
115//! use shell::ShellResult;
116//! use shell::ShellResultExt;
117//!
118//! # fn main() {
119//! let handle = shell::spawn(|| -> ShellResult {
120//!   cmd!("sleep 3").run()
121//! });
122//! handle.signal(libc::SIGINT);
123//! let result = handle.join().unwrap();
124//! assert!(result.is_err(), "Should be error as it exits with a signal");
125//! assert!(result.status().is_ok(), "Still able to obtain status");
126//! # }
127//! ```
128//!
129//! ## Signal handling
130//!
131//! `trap_signal_and_wait_children()` starts watching SIGINT and SIGTERM, and
132//! waits all child processes before exiting the process when receiving these
133//! signals. The function needs to be called before launching any new thread.
134//!
135//! ```
136//! extern crate shell;
137//! shell::trap_signal_and_wait_children().unwrap();
138//! ```
139//!
140//! ## Access underlaying objects
141//!
142//! `ShellComamnd` wraps `std::process::Command` and `ShellChild` wraps
143//! `std::process::Child`. Both underlaying objects are accessible via public
144//! fields.
145//!
146//! ```
147//! #[macro_use] extern crate shell;
148//! use std::process::Stdio;
149//! use std::io::Read;
150//!
151//! # fn main() {
152//! // Access std::process::Command.
153//! let mut shell_command = cmd!("echo OK");
154//! {
155//!   let mut command = &mut shell_command.command;
156//!   command.stdout(Stdio::piped());
157//! }
158//!
159//! // Access std::process::Child.
160//! let shell_child = shell_command.spawn().unwrap();
161//! {
162//!   let mut lock = shell_child.0.write().unwrap();
163//!   let mut child = &mut lock.as_mut().unwrap().child;
164//!   let mut str = String::new();
165//!   child.stdout.as_mut().unwrap().read_to_string(&mut str);
166//! }
167//! shell_child.wait().unwrap();
168//! # }
169//! ```
170//!
171//! ## License
172//! Apatch 2 License
173
174#[macro_use] extern crate lazy_static;
175#[macro_use] extern crate log;
176#[macro_use] extern crate nom;
177extern crate errno;
178extern crate libc;
179extern crate regex;
180extern crate env_logger;
181
182#[macro_use] mod command;
183mod shell_child;
184mod shell_command;
185mod process_manager;
186mod local_shell;
187mod result;
188
189pub use command::new_command;
190pub use local_shell::ShellHandle;
191pub use local_shell::spawn;
192pub use process_manager::trap_signal_and_wait_children;
193pub use result::ShellError;
194pub use result::ShellResult;
195pub use result::ShellResultExt;
196pub use result::ok;
197pub use shell_child::ShellChild;
198pub use shell_child::ShellChildArc;
199pub use shell_child::ShellChildCore;
200pub use shell_command::ShellCommand;