Skip to content

Dpbm/video-shebang

Repository files navigation

Notes

  • The name cames from Sharp-bang (#! from music sheet notation). Some say that it's due to its phonetics (hash + bang).
  • It especifies an interpreter for this script.
  • Bash handles the shebang when the underlying system doesn't do that.
  • It's usual to set it to #!/bin/bash to ensure that it will use Bash instead of any other shell.
  • Now days it's preferable to use #!/usr/bin/env bash to get bash from $PATH if installed in a different directory.
  • The script fallback to its parent SHELL when no shebang is defined.
  • The shebang is used for portability.
  • When it's not provided, the system raises an ENOEXEC (Exec Format error) error.
  • file command uses the shebang, as well, to see which kind of executable is that.
  • You don't need a blank after #!.
  • Also accepts relative paths.
  • When a program runs in a unix-like system, it executes a kernel exec()(or any command from this family) function. It take a look at the first 16 bits, searching for a magic number that describes an executable. If it's no signature is found it return an ENOEXEC error.
  • As time went, this magic part of the file also described how to execute it.
  • When the run starts running your script, it first tries to delegate it to the kernel, which search for the shebang and tries to execute the file with a different interpreter. If none was found, the bash itself tries to execute.
  • Explicit calling a script via a shell command (like sh or bash) the shebang is ignored.
  • Using /usr/bin/env doesn't provide complete portability, but it's a good practice.
  • Arguments can be split differently in different systems, so it may break in some occasions.
  • The path of the script is passed via argv to the interpreter.

Calling trace

execve -> do_execveat_common -> create a linux_binprm containing data from it (DEFINE_CLASS -> alloc_bprm ) -> bprm_execve -> exec_binprm -> search_binary_handler -> prepare_binprm -> kernel_read (read the file) ->

it them iterates over a linked list of formats

list_for_each_entry(fmt, &formats, lh) {

the exec.c provides an external function `__register_binfmt` that is used by each type in `binfmt_*.c` to register in the lits, calling like:

core_initcall(init_elf_binfmt);


-> load_binary from struct linux_binprm

if it's a script, it loads `binfmt_script.c` that has the method `load_script` which checks for the shebang

-> open_exec (from exec.c) -> do_open_execat

References