1

My script creates a chroot cage to install GRUB to a USB, run as sudo of course:

SYSTEM_DIRS=(etc bin sbin var lib lib64 usr proc sys dev tmp)

boot_partition=/media/user/boot

for dir in ${SYSTEM_DIRS[@]}; do
  mount --bind /$dir ${boot_partition}/${dir}
done

Then execute some commands inside the the chroot:

chroot ${boot_partition}/ touch foo # works fine
...

But when I want to execute the command exit

chroot ${boot_partition}/ exit

I get:

chroot: failed to execute the command <<exit>>: No such file or directory

Why does this happen and there is a way to fix it?

schrodingerscatcuriosity
  • 12,087
  • 3
  • 29
  • 57
  • 1
    What do you actually mean by "exit the chroot"? The `chroot` command changes the root directory for e.g. `touch foo` (or whatever command you execute), but it does not change it for _the script_, so "exiting it" makes no sense. `exit` is a shell built-in, and there is no external equivalent utility, so it can't execute it. – Kusalananda Jun 06 '19 at 21:56
  • @Kusalananda I'm following this: https://unix.stackexchange.com/a/61888/338177: "You have to first exit the chroot session, usually a simple exit will do:". I don't mean exiting the script, but terminate the chroot. `(chroot)root@foo:/# exit` – schrodingerscatcuriosity Jun 06 '19 at 22:01
  • 1
    They are probably starting an interactive shell through `chroot`. That shell has to exit. Extiing the chrooted shell will give control back to the non-chrooted shell session. The `chroot` command only affects the command that it runs. There is no indication in your question that you run `chroot "${boot_partition}/" bash`. – Kusalananda Jun 06 '19 at 22:03
  • Which I can do directly on the terminal. – schrodingerscatcuriosity Jun 06 '19 at 22:03
  • @Kusalananda I think I understand now. When I execute all this from the terminal it creates an interactive shell, isn't it? – schrodingerscatcuriosity Jun 06 '19 at 22:08

2 Answers2

3

exit is a shell built-in rather than a standalone executable, which means it cannot be executed by chroot. However, even if it could your command would do nothing.

This command runs /executable in the context of a /path chroot:

chroot /path /executable

It does not leave the caller inside that chroot; there's an implicit exit as soon as /executable finishes running:

mkdir -p /tmp/cr/{bin,lib,lib64}
cp -p /bin/pwd /tmp/cr/bin
cp -p $(find /lib* /usr/lib* -name 'libc.so*') /tmp/cr/lib
cp -p $(find /lib* /usr/lib* -name 'ld-linux-x86-64.so*') /tmp/cr/lib64

/bin/pwd                   # "/root"
chroot /tmp/cr /bin/pwd    # "/"
/bin/pwd                   # "/root"
roaima
  • 107,089
  • 14
  • 139
  • 261
0

I meet same question, my solution is when you execute chroot, append exit after it:

chroot /chroot_path && exit

then if user exit chroot, will exit the whole shell

Xilang
  • 101