feat: detect shell for --kernel
- Move detect_shell() to new src/utils.rs for reuse - Use detected shell in QEMU VM mode (bash when available) - Update chroot.rs and qemu_vm.rs to use shared function
This commit is contained in:
+3
-12
@@ -18,22 +18,13 @@ pub fn run_chroot(
|
||||
eprintln!("Warning: Failed to set hostname: {}", e);
|
||||
}
|
||||
|
||||
// Detect shell before chroot (we're still outside)
|
||||
let shell = crate::utils::detect_shell(rootfs);
|
||||
|
||||
// Change to root directory in chroot
|
||||
chroot(rootfs).context("Failed to chroot")?;
|
||||
|
||||
// Now we're inside the chroot - set up environment based on chroot filesystem
|
||||
// Determine shell path (check inside chroot, not host)
|
||||
let shell = if Path::new("/bin/bash").exists() {
|
||||
"/bin/bash"
|
||||
} else if Path::new("/bin/sh").exists() {
|
||||
"/bin/sh"
|
||||
} else if Path::new("/usr/bin/bash").exists() {
|
||||
"/usr/bin/bash"
|
||||
} else if Path::new("/usr/bin/sh").exists() {
|
||||
"/usr/bin/sh"
|
||||
} else {
|
||||
"/bin/sh" // Will fail with clear error if not present
|
||||
};
|
||||
|
||||
// Set up environment variables (after chroot, so paths are correct)
|
||||
let env = setup_environment(shell, &host_term);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod chroot;
|
||||
mod utils;
|
||||
mod cli;
|
||||
mod config;
|
||||
mod distro;
|
||||
|
||||
+7
-4
@@ -54,6 +54,9 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
||||
qemu_bin, get_arch_package_suffix(&config.arch), get_arch_package_suffix(&config.arch), get_arch_package_suffix(&config.arch)
|
||||
))?;
|
||||
|
||||
// Detect the best available shell in the rootfs
|
||||
let shell = crate::utils::detect_shell(&config.rootfs_path);
|
||||
|
||||
// Generate a unique hostname like "ecr-vm-a1b2c3"
|
||||
let hostname_suffix = format!("{:x}", (std::process::id() as u64)
|
||||
.wrapping_mul(std::time::SystemTime::now()
|
||||
@@ -72,14 +75,14 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
||||
let kernel_append = if let Some(ref cmd) = config.command {
|
||||
let cmd_str = cmd.join(" ");
|
||||
format!(
|
||||
"console=ttyS0 quiet rdinit=/bin/sh -- -c \"echo {} >/etc/hostname; hostname {}; setsid sh -c 'exec sh </dev/ttyS0 >/dev/ttyS0 2>&1 -c {}'\"",
|
||||
hostname, hostname, cmd_str
|
||||
"console=ttyS0 quiet rdinit=/bin/sh -- -c \"echo {} >/etc/hostname; hostname {}; setsid sh -c 'exec {} </dev/ttyS0 >/dev/ttyS0 2>&1 -c {}'\"",
|
||||
hostname, hostname, shell, cmd_str
|
||||
)
|
||||
} else {
|
||||
// Default to interactive shell with proper job control
|
||||
format!(
|
||||
"console=ttyS0 quiet rdinit=/bin/sh -- -c \"echo {} >/etc/hostname; hostname {}; setsid sh -c 'exec sh </dev/ttyS0 >/dev/ttyS0 2>&1'\"",
|
||||
hostname, hostname
|
||||
"console=ttyS0 quiet rdinit=/bin/sh -- -c \"echo {} >/etc/hostname; hostname {}; setsid sh -c 'exec {} </dev/ttyS0 >/dev/ttyS0 2>&1'\"",
|
||||
hostname, hostname, shell
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
use std::path::Path;
|
||||
|
||||
/// Detect the best available shell in a rootfs
|
||||
/// Checks for bash first, falls back to sh
|
||||
/// Returns the path relative to the rootfs (e.g., "/bin/bash")
|
||||
pub fn detect_shell(rootfs: &Path) -> &'static str {
|
||||
// Check for bash first (preferred)
|
||||
if rootfs.join("bin/bash").exists() {
|
||||
"/bin/bash"
|
||||
} else if rootfs.join("bin/sh").exists() {
|
||||
"/bin/sh"
|
||||
} else if rootfs.join("usr/bin/bash").exists() {
|
||||
"/usr/bin/bash"
|
||||
} else if rootfs.join("usr/bin/sh").exists() {
|
||||
"/usr/bin/sh"
|
||||
} else {
|
||||
"/bin/sh" // Will fail with clear error if not present
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user