在 Rust 中查找当前交互式 shell 的名称

问题描述 投票:0回答:1

我正在尝试获取正在执行命令行程序的当前交互式 shell 的名称。在我的终端中,我可以运行以下命令:

λ ps -p $$ -o 'comm='
zsh

并且它正确地打印了 shell 的名称。如果我用

sh -c
运行它,会得到相同的结果:

λ sh -c "ps -p $$ -o 'comm='"
zsh

用 Bash 尝试,结果相同:

λ bash
amir@shabani:~/Code/ami$ ps -p $$ -o 'comm='
bash
amir@shabani:~/Code/ami$ sh -c "ps -p $$ -o 'comm='"
bash

现在,当我在 Rust 程序中执行相同的命令时,它会打印

sh

use std::process::{Command, ExitCode};

pub fn shell() -> ExitCode {
    let output = Command::new("sh")
        .arg("-c")
        .arg("ps -p $$ -o 'comm='")
        .output()
        .expect("Failed to execute command");

    if output.status.success() {
        let shell_name = String::from_utf8_lossy(&output.stdout);
        println!("The current shell is: {}", shell_name.trim());
        ExitCode::SUCCESS
    } else {
        eprintln!("Error executing command");
        ExitCode::FAILURE
    }
}

无论我在哪里运行程序,

zsh
bash
,它总是打印
sh
。有什么问题吗?

shell rust
1个回答
2
投票

获得 something 的最简单方法是获取父进程(生成进程)的名称。这不一定是生成您的 shell:如果您通过

cargo run
运行程序,例如它将是 Cargo。但如果你直接从 shell 运行程序,它就会是你想要的。

您可以使用

sysinfo
crate 以跨平台的方式获取父进程:

fn main() {
    let system = sysinfo::System::new_with_specifics(
        sysinfo::RefreshKind::new().with_processes(sysinfo::ProcessRefreshKind::new()),
    );
    let my_pid = sysinfo::get_current_pid().expect("unable to get PID of the current process");
    let parent_pid = system
        .process(my_pid)
        .expect("no self process?")
        .parent()
        .expect("unable to get parent process");
    let parent_process = system
        .process(parent_pid)
        .expect("unable to get parent process");
    let parent_name = parent_process.name();

    println!("Spawning shell (or not): {parent_name}");
}

如果你想要更精确的分析,你可以从枚举所有活着的 shell 进程开始,并递归地询问它们的子进程。如果您的进程在列表中,则意味着它是从此 shell 生成的(直接或间接)。 请注意,这仅在 shell 还活着的情况下才有效;如果退出就无法工作。

© www.soinside.com 2019 - 2024. All rights reserved.