34

I'm trying to execute python scripts automatically generated by zc.buildout so I don't have control over them. My problem is that the shebang line (#!) is too long for either bash (80 character limit) or direct execution (some Linux kernel constant I don't know).

This is an example script to help you reproduce my problem:

#!/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././bin/bash
echo Hola!

How can be bash or the kernel configured to allow for bigger shebang lines?

sortega
  • 1,128
  • 9
  • 15
  • 1
    If you pass the script as an argument to the interpreter (`bash x.sh` rather than `./x.sh`) the shebang line would just be ignored as a comment and should not affect the execution. – Shawn Chin May 30 '12 at 09:39
  • I know, the problem is that I'm not the one invoking those scripts either... – sortega May 31 '12 at 09:28

3 Answers3

38

Limited to 127 chars on 99.9% of systems due to kernel compile time buffer limit.

It's limited in the kernel by BINPRM_BUF_SIZE, set in include/linux/binfmts.h.

sorin
  • 161,544
  • 178
  • 535
  • 806
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 7
    See also `man execve`: "A maximum line length of 127 characters is allowed for the first line in a #! executable shell script." – glenn jackman May 31 '12 at 00:32
14

If you don't want to recompile your kernel to get longer shebang lines, you could write a wrapper:

#!/bin/bash

if [[ $# -eq 0 ]]; then
    echo "usage: ${0##*/} script [args ...]"
    exit
fi

# we're going to expand a variable *unquoted* to use word splitting, but
# we don't want to have path expansion effects, so turn that off
set -f

shebang=$(head -1 "$1")
if [[ $shebang == '#!'* ]]; then
    interp=( ${shebang#\#!} )        # use an array in case a argument is there too
else
    interp=( /bin/sh )
fi

# now run it
exec "${interp[@]}" "$@"

and then run the script like: wrapper.sh script.sh

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
10

Updated @glenn jackman's script to support passing in command line arguments.

Incidentally, I ran into this problem when creating a python virtualenv inside of a very deep directory hierarchy.

In my case, this was a virtualenv created inside a Mesos framework dir.

The extra long shebang rendered calling xxx/.../venv/bin/pip useless.

The wrapper script proved most useful.

#!/usr/bin/env bash

script="$1" 
shebang=$(head -1 "$script")

# use an array in case a argument is there too
interp=( ${shebang#\#!} )        

# now run it, passing in the remaining command line arguments
shift 1
exec "${interp[@]}" "$script" "${@}"
coderfi
  • 378
  • 3
  • 7
  • 2
    Can you elaborate on how you're using this script with the virtual env? Our build fails during the initial creation of the virtual env because the #! path to easy_install is too long already. – Blaskovicz Apr 21 '15 at 18:55