/programming-language/cases/rust/std/process.rst

https://github.com/wdv4758h/notes · ReStructuredText · 179 lines · 132 code · 47 blank · 0 comment · 0 complexity · a5239ccc7914d630ebed6f5c0e17956d MD5 · raw file

  1. ========================================
  2. std::process
  3. ========================================
  4. .. contents:: 目錄
  5. 使用
  6. ========================================
  7. Command ::
  8. A process builder, providing fine-grained control over how a new process should be spawned.
  9. ``std::process::Command`` 實做採用了 Builder pattern
  10. 使用上是直接用 ``new`` 建一個新的
  11. 此時會具有現在程式的環境變數執行路徑stdin/stdout/stderr
  12. 建完之後可以再補上想要的參數
  13. 底下是把各平台的 ``Command`` 實做抽開
  14. sys 底下根據各平台特製實做
  15. ``libstd/process.rs`` 把平台特製實做包裝成統一的界面
  16. 實做
  17. * https://github.com/rust-lang/rust/blob/master/src/libstd/process.rs
  18. * https://github.com/rust-lang/rust/blob/master/src/libstd/sys_common/process.rs
  19. * https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/process/process_unix.rs
  20. 使用範例
  21. .. code-block:: rust
  22. use std::process::{Command, Stdio}; // command builder, stdio control
  23. use std::os::unix::process::CommandExt; // Unix-like only methods, e.g. uid, gid
  24. ////////////////////
  25. // 執行方式一: .output()
  26. let output =
  27. Command::new("echo")
  28. // 指令參數
  29. .arg("aaa")
  30. .arg("bbb")
  31. .args(&["ccc", "ddd"])
  32. .arg("eee")
  33. .args(&["fff", "ggg"])
  34. // 環境變數設定
  35. // 目前底下是用 BTreeMap 來儲存的
  36. .env_clear()
  37. .envs({
  38. use std::env;
  39. use std::collections::HashMap;
  40. env::vars().filter(|&(ref k, _)|
  41. k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
  42. ).collect::<HashMap<String, String>>()
  43. })
  44. .envs({
  45. use std::collections::HashMap;
  46. [
  47. ("MY_VAR1", "var1"),
  48. ("MY_VAR2", "var2"),
  49. ("MY_VAR3", "var3"),
  50. ].iter()
  51. .cloned()
  52. .collect::<HashMap<&str, &str>>()
  53. })
  54. .env("MY_VAR1", "foo")
  55. .env("MY_VAR2", "bar")
  56. .env_remove("MY_VAR1")
  57. .env("MY_VAR1", "foo2")
  58. // 更改執行資料夾
  59. .current_dir("/tmp")
  60. // 更改 stdin/stdout/stderr
  61. .stdin(Stdio::null())
  62. .stdout(Stdio::piped())
  63. .stderr(Stdio::piped())
  64. // 在 Unix-like 平臺可以設定 user ID 和 group ID
  65. .uid(1000)
  66. .gid(10)
  67. // 執行並取得結果
  68. .output()
  69. .expect("command failed to execute");
  70. println!("{:?}", output.stdout);
  71. println!("{:?}", output.stderr);
  72. println!("{:?}", output.status);
  73. println!("---");
  74. ////////////////////
  75. // 執行方式二: .status()
  76. // 只想知道執行是否成功,不想取得執行輸出
  77. let status = Command::new("echo")
  78. .arg("123")
  79. .status()
  80. .expect("command failed to execute");
  81. println!("{:?}", status);
  82. println!("---");
  83. ////////////////////
  84. // 執行方式三: .spawn()
  85. // 取得 child process 來做更多細部操作
  86. let mut child = Command::new("sleep")
  87. .arg("2")
  88. .spawn()
  89. .expect("command failed to execute");
  90. println!("{:?}", child);
  91. // methods:
  92. // * child.wait()
  93. // * child.try_wait()
  94. // * child.wait_with_output()
  95. // * child.kill()
  96. match child.try_wait() {
  97. Ok(Some(status)) => println!("exited with: {}", status),
  98. Ok(None) => println!("command not ready yet"),
  99. Err(e) => println!("error attempting to wait: {}", e),
  100. }
  101. println!("---");
  102. commands pipe
  103. ========================================
  104. .. code-block:: rust
  105. // echo "0123456789" | grep -o "4567" | sed "s/56/65/"
  106. use std::process::{Command, Stdio};
  107. let child1 = Command::new("echo")
  108. .arg("0123456789")
  109. .stdout(Stdio::piped())
  110. .spawn()
  111. .expect("Failed to start echo process");
  112. let child2 = Command::new("grep")
  113. .arg("-o")
  114. .arg("4567")
  115. .stdin(Stdio::from(child1.stdout.expect("failed to open stdout")))
  116. .stdout(Stdio::piped())
  117. .spawn()
  118. .expect("Failed to start sed process");
  119. let result = Command::new("sed")
  120. .arg("s/56/65/")
  121. .stdin(Stdio::from(child2.stdout.expect("failed to open stdout")))
  122. .stdout(Stdio::piped())
  123. .output()
  124. .expect("Failed to start sed process");
  125. println!("{:?}", result.status);
  126. println!("{:?}", String::from_utf8(result.stdout).unwrap());
  127. println!("{:?}", String::from_utf8(result.stderr).unwrap());
  128. Rust std::process v.s. Python subprocess
  129. ========================================
  130. * https://github.com/python/cpython/blob/master/Lib/subprocess.py
  131. 參考
  132. ========================================