/src/lib.rs

https://github.com/google/rust-shell · Rust · 200 lines · 25 code · 4 blank · 171 comment · 0 complexity · 5ceea4b0e5f9738724afc4f39ea325c1 MD5 · raw file

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