I have a foo.sh file in my current directory. If I try to run ./foo.sh, I get:

-bash: ./foo.sh: /bin/sh: bad interpreter: Permission denied

But if I run /bin/sh ./foo.sh then it runs fine.

How can I fix this so I can just run ./foo.sh and it automatically runs it with /bin/sh?

Edit: Okay, this is Chrome OS and this particular folder is mounted with noexec. Apparently that foils the ability to just run ./foo.sh; but why? Why can I still run sh foo.sh to achieve the exact same thing? What security, then, does noexec give?

  • 1
    security through obscurity Mar 6, 2017 at 0:36
  • Did you try if running ". foo.sh" works? May 26, 2019 at 7:14
  • @DanieleTesta This question is an ancient relic from a time long past. I was using a Google Cr-48, one of the first chromebooks, running a pretty early (but stable) version of ChromeOS. We've come a long way since then and I don't think this question would apply to the latest ChromeOS versions, but I haven't used it to say for sure. Anyway I think your variation would also have worked but one should test it before saying for sure. I am still unclear on exactly how noexec works its magic.
    – Ricket
    May 26, 2019 at 20:00

5 Answers 5


The noexec flag will appropriately apply to scripts, because that would be the "expected" behavior.

However, setting noexec only stops people who don't know enough about what they're doing. When you run sh foo.sh you're actually running sh from its default location (probably /bin) which is not on a filesystem mounted with noexec.

You can even get around noexec for regular binary files by invoking ld directly.

cp /bin/bash $HOME
/lib/ld-2.7.so $HOME/bash

This will run bash, regardless of whether or not it's on a filesystem mounted with noexec.

  • 5
    +1 for mentioning ld.so (clever) Feb 3, 2011 at 3:59
  • I tried your two commands; "cannot open shared object file: No such file or directory" - due to sh being copied but bash being run. So then I tried /lib/ld-2.10.1.so $HOME/sh and it returned another error while loading shared libraries: /home/chronos/user/sh: failed to map segment from shared object: Operation not permitted. I'm not sure if what you said was untrue, or if something else is interfering. For example, / is mounted as read-only.
    – Ricket
    Feb 3, 2011 at 4:06
  • Well, I couldn't say for certain because I don't have a copy of ChromeOS to try with. I'm fairly confident that it can work with some modification but without being able to try it myself I don't know what that might be.
    – bahamat
    Feb 3, 2011 at 15:21
  • Oh well, I'd like to think that it's because Chrome OS is properly locked down. It does seem to be pretty secure but I guess we'll see over time!
    – Ricket
    Feb 4, 2011 at 4:09
  • 1
    There's a difference between ld and ld.so. ld is a linker used in linking object code to form a binary when compiling, while ld.so is the run-time linker performing a similar action when executing a program. The linker referred to here is the run-time linker.
    – Kusalananda
    Mar 6, 2017 at 7:41

You can also get this error (or a very, very similar message) if you try to execute a file with MS-DOS 2-byte (carriage-return linefeed) line endings.

Vim is so smart these days, that it doesn't neccessarily show you the carriage returns as '^M'. So you can get fooled if you don't check what Vim thinks the "file format" is and just rely on the on-screen-appearance.

In this case the "#!/bin/sh^M" causes the kernel to try to find "/bin/sh^M", which it can't. Bad interpreter, indeed.


If you have the option to run the script or program from a USB stick (or other removable media), you can try unmounting and manually re-mounting it:

  1. Plug in USB stick

  2. Find USB stick device with $ mount

  3. Take note of it; let's assume it is /dev/sdb1

  4. Unmount USB stick:

    $ cd /media/removable
    $ sudo umount mountpoint

Finally, re-mount USB stick:

$ sudo mount /dev/sdb1 mountpoint

With mountpoint the USB stick's mount name


For system security reasons on ChromeOS/ChromiumOS certain folders are marked noexec and you either need to remount with the command below, or use an alternate path that doesn't have noexec set, like the second example.

These commands assume you are at least in developer mode and have access to the shell with chronos@localhost / $ and not just crosh> and know the sudo password.

sudo mount -i -o remount,exec /home/chronos/user/

The more sustainable method that should survive an upgrade because Google reserves most of /usr/local for developers:

sudo mkdir -p /usr/local/bin/ && sudo chown -R chronos: /usr/local/bin/
cp ${HOME}/Downloads/foo.sh /usr/local/bin/

The additional benefit of putting things here is that it is in the $PATH already (try echo $PATH to confirm this) so you don't need to use the full path to run scripts or binaries that are in /usr/local/bin and have had chmod +x run on them.

  • 2
    Hi, welcome on the Unix SE! Note, single-command answers aren't considered very HQ here. I suggest to explain, what are you doing and why.
    – peterh
    Jul 23, 2018 at 14:57

I had the same question. My problem was with the SD card. This worked for me, and it's much simpler than the other answers here. I learned it from Crouton issue #928.

$ sudo mount -o remount,exec /media/removable/SD\ Card

Note that you have to use the mount point, not the device (/dev/mmcblk1p1). Same thing for USB (/dev/sdb1) in your case. Only the mount point is different:

$ sudo mount -o remount,exec /media/removable/USB\ Drive

You'll know it had the desired effect because "noexec" will disappear from the mount options when you query.

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.