Movatterモバイル変換


[0]ホーム

URL:


Rust Cookbook

    External Command

    Run an external command and process stdout

    std-badgecat-os-badge

    Runsgit log --oneline using an externalCommand and inspects theOutputstatus to determine if the command was successful. The command output is capturedas a [String] using [String::from_utf8].

    use anyhow::{Result, anyhow};use std::process::Command;fn main() -> Result<()> {    let output = Command::new("git").arg("log").arg("--oneline").output()?;    if output.status.success() {        let raw_output = String::from_utf8(output.stdout)?;        let lines = raw_output.lines();        println!("Found {} lines", lines.count());        Ok(())    } else {        return Err(anyhow!("Command executed with failing error code"));    }}

    Run an external command passing it stdin and check for an error code

    std-badgecat-os-badge

    Opens thepython interpreter using an externalCommand and passes it apython statement for execution.Output of statement is then parsed.

    use anyhow::{Result, anyhow};use std::collections::HashSet;use std::io::Write;use std::process::{Command, Stdio};fn main() -> Result<()> {    let mut child = Command::new("python").stdin(Stdio::piped())        .stderr(Stdio::piped())        .stdout(Stdio::piped())        .spawn()?;    child.stdin        .as_mut()        .ok_or_else(|| anyhow!("Child process stdin has not been captured!"))?        .write_all(b"import this; copyright(); credits(); exit()")?;    let output = child.wait_with_output()?;    if output.status.success() {        let raw_output = String::from_utf8(output.stdout)?;        let words = raw_output.split_whitespace()            .map(|s| s.to_lowercase())            .collect::<HashSet<_>>();        println!("Found {} unique words:", words.len());        println!("{:#?}", words);        Ok(())    } else {        let err = String::from_utf8(output.stderr)?;        return Err(anyhow!("External command failed:\n {}", err));    }}

    Run piped external commands

    std-badgecat-os-badge

    Shows up to the 10th biggest files and subdirectories inthe current working directory. It is equivalent to running:du -ah . | sort -hr | head -n 10.

    Commands represent a process. Output of a child process is captured with aStdio::piped between parent and child.

    use anyhow::Result;use std::process::{Command, Stdio};fn main() -> Result<()> {    let directory = std::env::current_dir()?;    let mut du_output_child = Command::new("du")        .arg("-ah")        .arg(&directory)        .stdout(Stdio::piped())        .spawn()?;    if let Some(du_output) = du_output_child.stdout.take() {        let mut sort_output_child = Command::new("sort")            .arg("-hr")            .stdin(du_output)            .stdout(Stdio::piped())            .spawn()?;        du_output_child.wait()?;        if let Some(sort_output) = sort_output_child.stdout.take() {            let head_output_child = Command::new("head")                .args(&["-n", "10"])                .stdin(sort_output)                .stdout(Stdio::piped())                .spawn()?;            let head_stdout = head_output_child.wait_with_output()?;            sort_output_child.wait()?;            println!(                "Top 10 biggest files and directories in '{}':\n{}",                directory.display(),                String::from_utf8(head_stdout.stdout).unwrap()            );        }    }    Ok(())}

    Redirect both stdout and stderr of child process to the same file

    std-badgecat-os-badge

    Spawns a child process and redirectsstdout andstderr to the samefile. It follows the same idea asrun piped externalcommands, howeverprocess::Stdiowrites to a specified file.File::try_clone references the same file handleforstdout andstderr. It will ensure that both handles write with the samecursor position.

    The below recipe is equivalent to run the Unix shell commandls . oops >out.txt 2>&1.

    use std::fs::File;use std::io::Error;use std::process::{Command, Stdio};fn main() -> Result<(), Error> {    let outputs = File::create("out.txt")?;    let errors = outputs.try_clone()?;    Command::new("ls")        .args(&[".", "oops"])        .stdout(Stdio::from(outputs))        .stderr(Stdio::from(errors))        .spawn()?        .wait_with_output()?;    Ok(())}

    Continuously process child process' outputs

    std-badgecat-os-badge

    InRun an external command and process stdout,processing doesn't start until externalCommand is finished.The recipe below callsStdio::piped to create a pipe, and readsstdout continuously as soon as theBufReader is updated.

    The below recipe is equivalent to the Unix shell commandjournalctl | grep usb.

    use std::process::{Command, Stdio};use std::io::{BufRead, BufReader, Error, ErrorKind};fn main() -> Result<(), Error> {    let stdout = Command::new("journalctl")        .stdout(Stdio::piped())        .spawn()?        .stdout        .ok_or_else(|| Error::new(ErrorKind::Other,"Could not capture standard output."))?;    let reader = BufReader::new(stdout);    reader        .lines()        .filter_map(|line| line.ok())        .filter(|line| line.find("usb").is_some())        .for_each(|line| println!("{}", line));     Ok(())}

    Read Environment Variable

    std-badgecat-os-badge

    Reads an environment variable viastd::env::var.

    use std::env;use std::fs;use std::io::Error;fn main() -> Result<(), Error> {    // read `config_path` from the environment variable `CONFIG`.    // If `CONFIG` isn't set, fall back to a default config path.    let config_path = env::var("CONFIG")        .unwrap_or("/etc/myapp/config".to_string());    let config: String = fs::read_to_string(config_path)?;    println!("Config: {}", config);    Ok(())}

    [8]ページ先頭

    ©2009-2025 Movatter.jp