Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization
linux
microvm
firecracker
1use anyhow::{anyhow, Context, Result};
2use std::process::{Command, Output, Stdio};
3
4pub fn has_sudo() -> bool {
5 Command::new("sudo")
6 .arg("-h")
7 .output()
8 .map(|output| output.status.success())
9 .unwrap_or(false)
10}
11
12pub fn is_root() -> bool {
13 unsafe { libc::getuid() == 0 }
14}
15
16pub fn run_command(command: &str, args: &[&str], use_sudo: bool) -> Result<Output> {
17 let mut cmd = if use_sudo {
18 if !has_sudo() && !is_root() {
19 return Err(anyhow!(
20 "sudo is required for command '{}', but not available",
21 command
22 ));
23 }
24 let mut c = Command::new("sudo");
25 c.arg(command);
26
27 match is_root() {
28 true => Command::new(command),
29 false => c,
30 }
31 } else {
32 Command::new(command)
33 };
34
35 let output = cmd
36 .args(args)
37 .stdin(Stdio::inherit())
38 .stderr(Stdio::piped())
39 .output()
40 .with_context(|| format!("Failed to execute {}", command))?;
41
42 if !output.status.success() {
43 let stderr = String::from_utf8_lossy(&output.stderr);
44 return Err(anyhow!("Command {} failed: {}", command, stderr));
45 }
46 Ok(output)
47}
48
49pub fn run_command_with_stdout_inherit(command: &str, args: &[&str], use_sudo: bool) -> Result<()> {
50 let mut cmd = if use_sudo {
51 if !has_sudo() && !is_root() {
52 return Err(anyhow!(
53 "sudo is required for command '{}', but not available",
54 command
55 ));
56 }
57 let mut c = Command::new("sudo");
58 c.arg(command);
59
60 match is_root() {
61 true => Command::new(command),
62 false => c,
63 }
64 } else {
65 Command::new(command)
66 };
67
68 let mut child = cmd
69 .args(args)
70 .stdin(Stdio::inherit())
71 .stderr(Stdio::inherit())
72 .stdout(Stdio::inherit())
73 .spawn()
74 .with_context(|| format!("Failed to execute {}", command))?;
75
76 let status = child.wait()?;
77
78 if !status.success() {
79 return Err(anyhow!(
80 "Command {} failed with status: {}",
81 command,
82 status
83 ));
84 }
85
86 Ok(())
87}