4

Description

Very same loop containing chroot command can be executed in terminal but can not be executed within a shell script.

Reproduction

  1. Create a basic (or copy of your) rootfs in /mnt/myrootfs

  2. Create a file in /mnt/myrootfs/tmp/hello.sh (and make it executable) with the following contents:

    #!/bin/bash
    echo "i am exiting."
    exit 
    
  3. Create the following script (./chroot-poll.sh):

    #!/bin/bash
    while sleep 1; do 
        echo "chrooting into the target..."
        sleep 1    
        sudo chroot /mnt/myrootfs /bin/bash --rcfile /tmp/hello.sh
    done
    

Result

Console output is as follows:

$ ./chroot-poll.sh 
chrooting into the target...
i am exiting
chrooting into the target...

[1]+  Stopped                 ./chroot-poll.sh

Why is this stopping? Bringing it foreground by fg makes it iterate once more, and it stops again.

Running within a terminal works:

Copying the contents of ./chroot-poll.sh and pasting directly into the terminal works as expected:

$ while sleep 1; do      echo "chrooting into the target...";     sleep 1    ;     sudo chroot /mnt/myrootfs /bin/bash --rcfile /tmp/hello.sh; done
chrooting into the target...
i am exiting
chrooting into the target...
i am exiting
chrooting into the target...
i am exiting
chrooting into the target...
i am exiting
chrooting into the target...
^C

Question

Why contents of a script can work in a terminal while script itself fails to execute?

2
  • I cannot reproduce with GNU bash, version 5.0.18(1)-release (x86_64-slackware-linux-gnu) on Slackware -current. When I run ./chroot-poll.sh it runs continuously Aug 25 '21 at 12:19
  • I can still reproduce the same problem with GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu). My target rootfs that I'm chrooting is Debian 10 Buster.
    – ceremcem
    Aug 26 '21 at 13:15
1
+100

There's something that I can't quite get to add up about this question and I believe it has something to do with the text:

[1]+  Stopped                 ./chroot-poll.sh

I've only every seen text like that when running a process in the background yet there's no & anywhere in the the question and you've not mentioned running the job in the background. As others note I can't reproduce your error except if I run the script in the background.

When I try running your script with ./chroot-poll.sh & rather than just ./chroot-poll.sh I get similar results to you, so I can only assume you are running it in the background.

Usually a job goes into Stopped when it is running in the background and attempts to read from the stdin. The very simple workaround for this can be to make it read from /dev/null instead:

./chroot-poll.sh < /dev/null

That way when anything attempts to read, it will read from /dev/null and not from stdin.


I believe this is ultimately happening because you are running bash in interactive mode. You are not asking it to execute a script, only override the ~/.bashrc. Despite the exit bash is still reading from stdin as if it expects you to type something at the prompt. To get bash to read the script as a script use:

sudo chroot /mnt/myrootfs /bin/bash -f /tmp/hello.sh
2
  • ./chroot-poll.sh < /dev/null makes the chrooting into the target... appear continuously, so I would assume the /tmp/hello.sh script runs continuously. However, when I add the echo $(($(</tmp/count) + 1)) > /tmp/count line to the /tmp/hello.sh, ./chroot-poll.sh < /dev/null stops after first iteration, leaving /tmp/count with content of 1. I also couldn't get how -f switch helps here.
    – ceremcem
    Aug 26 '21 at 13:25
  • 1
    My mistake, I didn't replace --rcfile with -f, I only added -f switch. Now I issued the command exactly you specified and it works as expected.
    – ceremcem
    Aug 26 '21 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.