Why does std::process::Command panic when I set a different root path with chroot() on ubuntu 20.04?

I am using Rust to do some file operations. I have a rootfs extracted from docker image and I want to copy some files in such rootfs to generate a new image. To simplify such a rootfs, I will init a new rootfs with following commands on my ubuntu 20.04:

mkdir rootfs
cp -a /usr rootfs/
cp -a /lib rootfs/
cp -a /lib64 rootfs/
cp -a /bin rootfs/

Now, I want to copy /usr/bin/ls to the root directoryt in rootfs. If I directly do these operations with shell, I will use

sudo chroot rootfs
cp -a /usr/bin/ls /

(I must use chroot here because I need to only use absolute paths for some reason. )

Then, I want to do the same operation with a simple Rust program. By refering the ducumentation about chroot, I write following rust codes. This program should be run with sudo privilege.

fn main() {
    let src = "/usr/bin/ls";
    let dest = "/ls";
    println!("cp -a {} {}", src, dest);
    // change root to our rootfs
    std::os::unix::fs::chroot("./rootfs").expect("chroot failed");
    std::env::set_current_dir("/").expect("set dir failed");
    // Method 1: fs::copy. This is Ok
    std::fs::copy(src, dest).expect("std::fs copy file failed");
    // Method 2: Command. This will fail
    match std::process::Command::new("cp").arg("-a").arg(src).arg(dest).output() {
        Ok(_) => {},
        Err(e) => {
            println!("Command: copy file {} to {} failed. {}", src, dest, e);
            std::process::exit(-1);
        }
    }
}

I have tried two possible methods. First is file operations defined in std::fs, this works fine. Second is std::process::Command, I use this method to call cp to do real file operations, however, this method always fails due to "No such file or directory" error. I have carefully checked that the file to copy and cp program do exist in rootfs. I can't determine why this program will panic.

So, I have such two questions:

  1. How to fix the panic problem if I want to use std::process::Command to do file operations in rootfs (chroot is required, so delete chroot is not an option) ?
  2. Which shell is the Command used after chroot, the shell on host or the shell in rootfs? And what‘s the current directory when I run Command?

Have you copied cp into the rootfs first at place in the PATH?

I have copied cp to the path that bash can find it, I can run cp -a /usr/bin/ls /ls in rootfs with bash. But I find that Command cannot find cp. So, how can I make Command execute cp in rootfs?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.