Shebang Not Working to Run Bash Scripts in Linux

Why does this sh shebang not work?

First, make the script executable:

chmod u+x script.sh

Second, your current directory is not in your $PATH. Therefore, you have to run the script with a path (relative is enough):

./script.sh

Bash script doesn't work without shebang BUT the shebang results in an error message

You have an encoding problem.

Look at: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8

A text editor or web browser misinterpreting the text as ISO-8859-1 or CP1252 will display the characters  for this.

Save your file as UTF-8 without BOM or use system editor (vi, ...)

Should I use a Shebang with Bash scripts?

On UNIX-like systems, you should always start scripts with a shebang line. The system call execve (which is responsible for starting programs) relies on an executable having either an executable header or a shebang line.

From FreeBSD's execve manual page:

 The execve() system call transforms the calling process into a new
process. The new process is constructed from an ordinary file, whose
name is pointed to by path, called the new process file.
[...]

This file is
either an executable object file, or a file of data for an interpreter.

[...]

An interpreter file begins with a line of the form:

#! interpreter [arg]

When an interpreter file is execve'd, the system actually execve's the
specified interpreter. If the optional arg is specified, it becomes the
first argument to the interpreter, and the name of the originally
execve'd file becomes the second argument

Similarly from the Linux manual page:

execve() executes the program pointed to by filename. filename must be
either a binary executable, or a script starting with a line of the
form:

#! interpreter [optional-arg]

In fact, if a file doesn't have the right "magic number" in it's header, (like an ELF header or #!), execve will fail with the ENOEXEC error (again from FreeBSD's execve manpage):

[ENOEXEC] The new process file has the appropriate access
permission, but has an invalid magic number in its
header.


If the file has executable permissions, but no shebang line but does seem to be a text file, the behaviour depends on the shell that you're running in.

Most shells seem to start a new instance of themselves and feed it the file, see below.

Since there is no guarantee that the script was actually written for that shell, this can work or fail spectacularly.

From tcsh(1):

   On  systems which do not understand the `#!' script interpreter conven‐
tion the shell may be compiled to emulate it; see the version shell
variable. If so, the shell checks the first line of the file to see if
it is of the form `#!interpreter arg ...'. If it is, the shell starts
interpreter with the given args and feeds the file to it on standard
input.

From FreeBSD's sh(1):

If the program is not a normal executable file (i.e., if it
does not begin with the “magic number” whose ASCII representation is
“#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
be a text file, the shell will run a new instance of sh to interpret it.

From bash(1):

   If this execution fails because the file is not in  executable  format,
and the file is not a directory, it is assumed to be a shell script, a
file containing shell commands. A subshell is spawned to execute it.

You cannot always depend on the location of a non-standard program like bash. I've seen bash in /usr/bin, /usr/local/bin, /opt/fsf/bin and /opt/gnu/bin to name a few.

So it is generally a good idea to use env;

#!/usr/bin/env bash

If you want your script to be portable, use sh instead of bash.

#!/bin/sh

While standards like POSIX do not guarantee the absolute paths of standard utilities, most UNIX-like systems seem to have sh in /bin and env in /usr/bin.

VS Code does not recognize shebang for bash

The "set the executable bit" trick works, but I'm not sure where that information is stored or if it's persisted across reboots. I just remembered a better solution: file associations!

Just add this to project/.vscode/vscode.json (the key should be the name of the file):

{
"files.associations": {
"jobname-batch": "bash"
}
}

Shell script saying Command not found. Ignoring shebang?

The reason for this can be one of several things. To list the most common:

  1. The file does not have executable permissions. Use chmod a+x foo.sh to give all users execute permissions.
  2. Your shebang is incorrect, double-check the path. Use which sh and copy the result after a #!
  3. Your lines are delimited with DOS feeds. Scripts need to be delimited with \n. Text editors such as nano allow you to convert by choosing Write-out then pressing Alt+D to toggle DOS format off. Utilities such as dos2unix can convert files directly on the command line (although it may need installing first).

Shell script working fine without shebang line? Why?

shebang line is needed in the file and only if it's meant to be run as executable (as opposed to sh file.sh invocation. It is not actually needed by script, it is for the system to know how to find interpreter.

EDIT: Sorry for misreading the question. If the shebang line is missing or not recognized, /bin/sh is used. But I prefer being explicit about the interpreter.

Note, that this behavior is not universal, IIRC, only some exec* family function do that (not to mention different platforms), so that's another reason to be explicit here.

Call a python script with a shebang

First, rename the file from foo.py to foo.

Then, move the file to /usr/local/bin/ or /home/user/.local/bin if the script will only be executed by a single user. Instead, if your script is placed somewhere in the system for example "/path/to/foo", you could add your "/path/to/foo" to the $PATH variable.

After opening a new terminal session. You should be able to execute the script without the "./" and ".py".

By the way "./" means that you want to execute a file in the current working directory. It is always possible to execute a file using a full path of the file, for example "/usr/bin/something_to_run".

Please consider reading about PATH variable here.

Do you need shebang in all bash scripts?

The shebang is only mandatory for those scripts, which shall be executed by the operating system in the same way as binary executables. If you source in another script, then the shebang is ignored.

On the other hand. IF a script is supposed to be sourced, then it is convention to NOT put any shebang at the start.



Related Topics



Leave a reply



Submit