1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
//! 特定于 Unix 的 [`std::process`] 模块中的原语扩展。
//!
//! [`std::process`]: crate::process
#![stable(feature = "rust1", since = "1.0.0")]
use crate::ffi::OsStr;
use crate::io;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::process;
use crate::sealed::Sealed;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] {
type UserId = u16;
type GroupId = u16;
} else if #[cfg(target_os = "nto")] {
// 两个 ID 都已签名,请参见 QNX Neutrino SDP 的 `sys/target_nto.h`。
// 只应使用正值,参见例如
// https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html
type UserId = i32;
type GroupId = i32;
} else {
type UserId = u32;
type GroupId = u32;
}
}
/// 特定于 Unix 的 [`process::Command`] 构建器扩展。
///
/// 这个 trait 是封闭的:它不能在标准库之外实现。
/// 这是为了将来的附加方法不会破坏更改。
#[stable(feature = "rust1", since = "1.0.0")]
pub trait CommandExt: Sealed {
/// 设置子进程的用户 ID。
/// 这将转换为子进程中的 `setuid` 调用。
/// `setuid` 调用失败将导致 spawn 失败。
#[stable(feature = "rust1", since = "1.0.0")]
fn uid(&mut self, id: UserId) -> &mut process::Command;
/// 与 `uid` 相似,但是设置子进程的组 ID。
/// 这具有与 `uid` 字段相同的语义。
#[stable(feature = "rust1", since = "1.0.0")]
fn gid(&mut self, id: GroupId) -> &mut process::Command;
/// 设置调用进程的补充组 ID。
/// 在子进程中转换为 `setgroups` 调用。
#[unstable(feature = "setgroups", issue = "90747")]
fn groups(&mut self, groups: &[GroupId]) -> &mut process::Command;
/// 计划在 `exec` 函数被调用之前运行一个闭包。
///
/// 允许闭包返回 I/O 错误,该错误的 OS 错误代码将被传达回父级,并从请求 spawn 开始作为错误返回。
///
/// 可以注册多个闭包,并且将按照注册顺序对其进行调用。如果闭包返回 `Err`,则不会再调用任何闭包,并且 spawn 操作将立即失败返回。
///
/// # 注意和安全
///
/// `fork` 之后,此闭包将在子进程的上下文中运行。这主要意味着,代表此闭包对内存所做的任何修改对于父进程都是不可见的。
/// 这通常是一个非常受限制的环境,无法保证正常操作 (如 `malloc`,通过 [`std::env`] 访问环境变量或获取互斥锁) (由于运行 `fork` 时可能仍在运行其他线程)。
///
/// 有关更多详细信息,请参见 [POSIX fork() 规范][POSIX fork() specification] 和任何目标平台的等效文档,尤其是有关 *async-signal-safety* 的要求。
///
/// 这也意味着所有资源 (例如文件描述符和内存映射的区域) 都被复制了。您有责任确保闭包不会因为无效使用这些副本而违反库不变量。
///
/// 只有当 panic 消息的所有格式参数都可以安全格式化时,闭包中的 panic 才是安全的; 这是因为尽管 `Command` 在调用 pre_exec 钩子之前调用了 [`std::panic::always_abort`](crate::panic::always_abort),但 panic 仍会尝试格式化 panic 消息。
///
///
/// 运行此闭包时,标准输入输出文件描述符和工作目录等方面已成功更改,因此这些位置的输出可能不会出现在预期的位置。
///
/// [POSIX fork() specification]:
/// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
/// [`std::env`]: mod@crate::env
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
///
#[stable(feature = "process_pre_exec", since = "1.34.0")]
unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
where
F: FnMut() -> io::Result<()> + Send + Sync + 'static;
/// 计划在 `exec` 函数被调用之前运行一个闭包。
///
///
/// 此方法稳定且可用,但不安全。
/// 为了解决这个问题,它不赞成使用不安全的 [`pre_exec`]。
///
/// [`pre_exec`]: CommandExt::pre_exec
#[stable(feature = "process_exec", since = "1.15.0")]
#[deprecated(since = "1.37.0", note = "should be unsafe, use `pre_exec` instead")]
fn before_exec<F>(&mut self, f: F) -> &mut process::Command
where
F: FnMut() -> io::Result<()> + Send + Sync + 'static,
{
unsafe { self.pre_exec(f) }
}
/// 通过此 `Command` 执行所有必需的设置,然后调用 `execvp` syscall。
///
/// 成功后,该函数将不会返回,否则它将返回错误,指示 exec (或 `Command` 的另一部分安装) 失败的原因。
///
/// `exec` 不返回与调用 [`process::exit`] 具有相同的含义 -- 当前栈或任何其他线程栈上的析构函数都不会运行。因此,建议仅在不运行任何析构函数的时候调用 `exec`。
///
/// 请注意,`execvp` 系统调用独立保证释放所有内存,并关闭所有带有 `CLOEXEC` 选项的文件描述符 (默认情况下在标准库打开的所有文件描述符上设置)。
///
/// 与 `spawn` 不同,此函数不会使用 `fork` 来创建一个新的子进程。但是,与 spawn 一样,标准输入输出描述符的默认行为将继承自当前进程。
///
/// # Notes
///
/// 如果此函数返回错误,则该进程可能在 "broken state" 中。例如,工作目录,环境变量,信号处理设置,各种 user/group 信息或标准输入输出文件描述符的各个方面可能已更改。
/// 如果需要 "事务性生成" 来妥善处理错误,建议改用跨平台 `spawn`。
///
///
///
///
///
///
///
///
///
///
///
///
///
#[stable(feature = "process_exec2", since = "1.9.0")]
fn exec(&mut self) -> io::Error;
/// 设置可执行参数
///
/// 将第一个进程参数 `argv[0]` 设置为默认可执行路径以外的其他值。
///
#[stable(feature = "process_set_argv0", since = "1.45.0")]
fn arg0<S>(&mut self, arg: S) -> &mut process::Command
where
S: AsRef<OsStr>;
/// 设置子进程的进程组 ID (PGID)。
/// 相当于子进程中的一个 `setpgid` 调用,但可能效率更高。
///
/// 进程组确定哪些进程接收信号。
///
/// # Examples
///
/// 在终端中按 Ctrl-C 将向当前前台进程组中的所有进程发送 SIGINT。
///
/// 通过在新进程组中生成 `sleep` 子进程,它将不会从终端接收 SIGINT。
///
/// 父进程可以安装信号处理程序并按照自己的条件管理子进程。
///
/// 进程组 ID 为 0 将使用进程 ID 作为 PGID。
///
/// ```no_run
/// use std::process::Command;
/// use std::os::unix::process::CommandExt;
///
/// Command::new("sleep")
/// .arg("10")
/// .process_group(0)
/// .spawn()?
/// .wait()?;
/// #
/// # Ok::<_, Box<dyn std::error::Error>>(())
/// ```
///
///
#[stable(feature = "process_set_process_group", since = "1.64.0")]
fn process_group(&mut self, pgroup: i32) -> &mut process::Command;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl CommandExt for process::Command {
fn uid(&mut self, id: UserId) -> &mut process::Command {
self.as_inner_mut().uid(id);
self
}
fn gid(&mut self, id: GroupId) -> &mut process::Command {
self.as_inner_mut().gid(id);
self
}
fn groups(&mut self, groups: &[GroupId]) -> &mut process::Command {
self.as_inner_mut().groups(groups);
self
}
unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
where
F: FnMut() -> io::Result<()> + Send + Sync + 'static,
{
self.as_inner_mut().pre_exec(Box::new(f));
self
}
fn exec(&mut self) -> io::Error {
// NOTE: 在 `libc::fork` 之后调用此方法可能不是 * 安全的,因为它可能会分配。
// 在 future 中的某个位置可能值得解决。
self.as_inner_mut().exec(sys::process::Stdio::Inherit)
}
fn arg0<S>(&mut self, arg: S) -> &mut process::Command
where
S: AsRef<OsStr>,
{
self.as_inner_mut().set_arg_0(arg.as_ref());
self
}
fn process_group(&mut self, pgroup: i32) -> &mut process::Command {
self.as_inner_mut().pgroup(pgroup);
self
}
}
/// 特定于 Unix 的 [`process::ExitStatus`] 和 [`ExitStatusError`](process::ExitStatusError) 的扩展。
///
/// 在 Unix 上,`ExitStatus`**不一定代表退出状态**,因为传递给 `_exit` 系统调用或由 [`ExitStatus::code()`](crate::process::ExitStatus::code) 返回。
/// 它表示由 `wait` 系列系统调用之一返回的**任何等待状态**。
///
/// Unix 等待状态 (Rust `ExitStatus`) 可以代表 Unix 退出状态,但也可以代表其他类型的进程事件。
///
/// 这个 trait 是封闭的:它不能在标准库之外实现。
/// 这是为了将来的附加方法不会破坏更改。
///
///
///
///
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExitStatusExt: Sealed {
/// 从 `wait` 的原始底层整数状态值创建一个新的 `ExitStatus` 或 `ExitStatusError`
///
///
/// 该值应该是等待状态,而不是退出状态。
///
/// # Panics
///
/// 尝试从 `0` 的等待状态生成 `ExitStatusError` 时出现 panic。
///
/// 创建 `ExitStatus` 总是会成功的,并且从不 panics。
#[stable(feature = "exit_status_from", since = "1.12.0")]
fn from_raw(raw: i32) -> Self;
/// 如果进程被一个信号终止,则返回该信号。
///
/// 换句话说,如果为 `WIFSIGNALED`,则返回 `WTERMSIG`。
#[stable(feature = "rust1", since = "1.0.0")]
fn signal(&self) -> Option<i32>;
/// 如果进程被一个信号终止,说明它是否丢弃了核心。
#[stable(feature = "unix_process_wait_more", since = "1.58.0")]
fn core_dumped(&self) -> bool;
/// 如果该进程被信号停止,则返回该信号。
///
/// 换句话说,如果为 `WIFSTOPPED`,则返回 `WSTOPSIG`。
/// 这仅在状态来自 `wait` 系统调用时才可能,该系统调用通过 `WUNTRACED`,然后转换为 `ExitStatus`。
#[stable(feature = "unix_process_wait_more", since = "1.58.0")]
fn stopped_signal(&self) -> Option<i32>;
/// 进程是否从停止状态继续。
///
/// 即,`WIFCONTINUED`。
/// 这只有在状态来自 `wait` 系统调用时才有可能,该系统调用通过 `WCONTINUED`,然后转换为 `ExitStatus`。
#[stable(feature = "unix_process_wait_more", since = "1.58.0")]
fn continued(&self) -> bool;
/// 返回底层的原始 `wait` 状态。
///
/// 返回的整数是等待状态,而不是退出状态。
#[stable(feature = "unix_process_wait_more", since = "1.58.0")]
fn into_raw(self) -> i32;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExitStatusExt for process::ExitStatus {
fn from_raw(raw: i32) -> Self {
process::ExitStatus::from_inner(From::from(raw))
}
fn signal(&self) -> Option<i32> {
self.as_inner().signal()
}
fn core_dumped(&self) -> bool {
self.as_inner().core_dumped()
}
fn stopped_signal(&self) -> Option<i32> {
self.as_inner().stopped_signal()
}
fn continued(&self) -> bool {
self.as_inner().continued()
}
fn into_raw(self) -> i32 {
self.as_inner().into_raw().into()
}
}
#[unstable(feature = "exit_status_error", issue = "84908")]
impl ExitStatusExt for process::ExitStatusError {
fn from_raw(raw: i32) -> Self {
process::ExitStatus::from_raw(raw)
.exit_ok()
.expect_err("<ExitStatusError as ExitStatusExt>::from_raw(0) but zero is not an error")
}
fn signal(&self) -> Option<i32> {
self.into_status().signal()
}
fn core_dumped(&self) -> bool {
self.into_status().core_dumped()
}
fn stopped_signal(&self) -> Option<i32> {
self.into_status().stopped_signal()
}
fn continued(&self) -> bool {
self.into_status().continued()
}
fn into_raw(self) -> i32 {
self.into_status().into_raw()
}
}
#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawFd for process::Stdio {
#[inline]
unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
let fd = sys::fd::FileDesc::from_raw_fd(fd);
let io = sys::process::Stdio::Fd(fd);
process::Stdio::from_inner(io)
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl From<OwnedFd> for process::Stdio {
#[inline]
fn from(fd: OwnedFd) -> process::Stdio {
let fd = sys::fd::FileDesc::from_inner(fd);
let io = sys::process::Stdio::Fd(fd);
process::Stdio::from_inner(io)
}
}
#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdin {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.as_inner().as_raw_fd()
}
}
#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStdout {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.as_inner().as_raw_fd()
}
}
#[stable(feature = "process_extensions", since = "1.2.0")]
impl AsRawFd for process::ChildStderr {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.as_inner().as_raw_fd()
}
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStdin {
#[inline]
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_inner().into_raw_fd()
}
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStdout {
#[inline]
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_inner().into_raw_fd()
}
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for process::ChildStderr {
#[inline]
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_inner().into_raw_fd()
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl AsFd for crate::process::ChildStdin {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
self.as_inner().as_fd()
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl From<crate::process::ChildStdin> for OwnedFd {
#[inline]
fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
child_stdin.into_inner().into_inner().into_inner()
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl AsFd for crate::process::ChildStdout {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
self.as_inner().as_fd()
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl From<crate::process::ChildStdout> for OwnedFd {
#[inline]
fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
child_stdout.into_inner().into_inner().into_inner()
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl AsFd for crate::process::ChildStderr {
#[inline]
fn as_fd(&self) -> BorrowedFd<'_> {
self.as_inner().as_fd()
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
impl From<crate::process::ChildStderr> for OwnedFd {
#[inline]
fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
child_stderr.into_inner().into_inner().into_inner()
}
}
/// 返回与此进程的父级关联的操作系统分配的进程标识符。
#[must_use]
#[stable(feature = "unix_ppid", since = "1.27.0")]
pub fn parent_id() -> u32 {
crate::sys::os::getppid()
}